问题
I have a time series of production in countries over time. I made this stacked area graph with the full data:
The problem is that it isn't very readable (since using all countries means I can't have a legend) so I thought that I wanted to somehow group the lowest producing countries and sort the graph on the production from highest to lowest. I think that grouping and sorting based on the last years (2017) values would make the most sense, since the production is usually much higher.
Here is a subset of the data
structure(list(country = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L,
4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L,
6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L,
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L,
9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L,
10L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L), .Label = c("Democratic People's Republic of Korea",
"Democratic Republic of the Congo", "Dominica", "Dominican Republic",
"Ecuador", "Egypt", "El Salvador", "Eswatini", "Fiji", "France",
"French Guiana"), class = "factor"), year = c(1961, 1962, 1963,
1964, 1965, 1966, 1967, 1968, 1969, 1970, 1961, 1962, 1963, 1964,
1965, 1966, 1967, 1968, 1969, 1970, 1961, 1962, 1963, 1964, 1965,
1966, 1967, 1968, 1969, 1970, 1961, 1962, 1963, 1964, 1965, 1966,
1967, 1968, 1969, 1970, 1961, 1962, 1963, 1964, 1965, 1966, 1967,
1968, 1969, 1970, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968,
1969, 1970, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969,
1970, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970,
1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1961,
1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1961, 1962,
1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970), value = c(1.245,
1.305, 1.43, 1.505, 1.315, 1.465, 1.365, 1.32, 1.62, 1.61, 0.37,
0.36, 0.35, 0.35, 0.35, 0.39, 0.41, 0.425, 0.43, 0.4281, 0.00013,
0.00013, 0.00014, 0.00014, 0.00015, 0.00015, 0.00016, 0.00016,
0.00016, 0.00016, 0.050233, 0.048464, 0.045583, 0.043198, 0.0375,
0.0425, 0.038548, 0.04, 0.043, 0.045, 0.153047, 0.138365, 0.191953,
0.12878, 0.191363, 0.174905, 0.227769, 0.173892, 0.211189, 0.256067,
1.61713, 2.00369, 1.867, 1.934212, 2.141, 2.376, 2.167, 2.3,
2.368, 2.397, 0.1763, 0.2139, 0.207077, 0.191611, 0.203006, 0.265914,
0.20884, 0.25755, 0.278967, 0.363078, 0.029991, 0.03486, 0.031751,
0.030481, 0.031751, 0.035017, 0.062595, 0.051709, 0.058107, 0.062595,
0.00022, 0.00022, 0.00025, 4e-04, 4e-04, 4e-04, 0.001996, 0.00375,
0.002, 0.000711, 2.48, 1.86656, 3.87707, 2.1088, 3.4678, 4.3402,
4.15219, 5.38958, 5.73, 7.491, 2e-04, 0.000405, 7e-05, 9.5e-05,
9.5e-05, 0.000111, 0.00011, 8.5e-05, 1e-04, 0.000225)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -110L))
Here is my code
library(ggplot2)
library(tidyverse)
plot_data %>%
ggplot(aes(x=year, y=value, fill=country)) +
geom_area()
I am not sure how to do this, but I started by making a rank based on the last year.
ordered_plot_data = plot_data %>%
filter(year == last(year)) %>%
arrange(desc(value)) %>%
mutate(rank = row_number())
So say I wanted to have three countries shown and the rested grouped into "others":
n_countries = 3
first_part = ordered_plot_data %>%
top_n(n_countries, value)
last_part = ordered_plot_data %>%
top_n(-(length(unique(ordered_plot_data$country))-n_countries), value) %>%
summarise(country = "Other",
year = first(year),
value = sum(value),
rank = n_countries + 1)
joined_data = rbind(first_part, last_part)
This gives me grouped data which is ordered but only for 2017. So I thought that I could use this somehow and for each year group according to the grouping I have made from 2017, but of course this just seem way too complicated and I over my head I would like some help with an easier way to solve this.
回答1:
The key thing is that you need to use that ordering to sort a factor variable. By default the first level of a factor is plotted at the top so you want it to go from "Other" through to the highest value. The following code should work for you!
library(ggplot2)
library(tidyverse)
plot_order = plot_data %>%
mutate(country = as.character(country)) %>%
filter(year == last(year)) %>%
arrange(desc(value)) %>%
mutate(rank = row_number())
n_countries = 3
final_plot <- plot_data %>%
mutate(country = as.character(country)) %>%
mutate(plot_label = ifelse(country %in% plot_order$country[1:n_countries], country, 'Other')) %>%
mutate(plot_label = factor(plot_label, levels = c('Other', rev(plot_order$country[1:n_countries])))) %>%
group_by(plot_label, year) %>%
summarise(value = sum(value))
final_plot %>%
ggplot(aes(x=year, y=value, fill=plot_label)) +
geom_area()
来源:https://stackoverflow.com/questions/58221360/group-lowest-values-and-sort-this-stacked-area-graph