I am trying to reorder factor levels in a tibble after using pivot_longer
. Ultimately, the goal is to plot the data in ggplot
and have the legend align with the order of the lines in the chart. I don't want to manually assign the levels each time. I'd like the factor ordered by one of the variables in the pivoted tibble. But that column has multiple values for each factor...
This has to be easier than I am making it!
Here is my code:
df <- tibble(Year=c(1900, 1901, 1903), Foo=c(9,30, 60), Bar=c(3,20, 50)) %>%
pivot_longer(!Year, names_to = "Name", values_to = "Count")
df$Name <- factor(df$Name)
Then levels(df$Name)
returns the default alphabetical order of [1] "Bar" "Foo"
. But I'd like to reorder that based on the maximum value each factor has in the Count
column of the tibble, i.e. [1] "Foo" "Bar"
in this case.
All of this is so I can plot the data and align the legend to the order of the lines in the chart (without setting the order of the levels manually). Here is my ggplot
code:
p <- ggplot(df, aes(x = Year, y = Count)) +
geom_line(aes(colour = Name))
p
And here is the plot:
Help? Thanks!
A little bit cumbersome, but we can first create a vector to get the levels order based on the maximum values per factor (here: foo = 60
, bar = 50
) and then use it as levels:
fac_order <- df1 %>%
pivot_longer(!Year, names_to = "Name", values_to = "Count") %>%
distinct(Count, .keep_all = TRUE) %>%
slice_max(Count, by = Name) %>%
arrange(desc(Count)) %>%
pull(Name)
df1 %>%
pivot_longer(!Year, names_to = "Name", values_to = "Count") %>%
mutate(Name = factor(Name, levels = fac_order)) %>%
ggplot(aes(x = Year, y = Count)) +
geom_line(aes(colour = Name))
The result remains the same.
You could use
library(tidyverse)
df1 <- tibble(Year=c(1900, 1901, 1903), Foo=c(9,30, 60), Bar=c(3,20, 50))
df1 %>%
pivot_longer(!Year, names_to = "Name", values_to = "Count") %>%
mutate(Name = fct_reorder(Name, Count, .desc = TRUE)) %>%
ggplot(aes(x = Year, y = Count)) +
geom_line(aes(colour = Name))
This returns