rggplot2levels

Reorder factor levels after pivot_longer


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:

enter image description here

Help? Thanks!


Solution

  • Update

    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.

    First Version

    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

    enter image description here