Search code examples
rggplot2legend-properties

How to order legend entries chronologically and not by value?


The plot (with my minimal reproducible code) shows a quantity that is consumed and to be replenished from time to time. The data is first grouped by month. Then, if the quantity is replenishment within a month the data points within that month become a separate group.

The legend entry is the slope of the line for each group. This results in the legend entries to be in increasing order.

I need the legend entries from top to bottom to follow the calendar order from left to right.

Thank you

mydata <-  read.table(header = TRUE, text = "
            data_date data_value
            2023-04-20 17
            2023-04-24 15
            2023-04-30 12
            2023-05-03 10
            2023-05-08  7
            2023-05-13  2
            2023-05-14 16
            2023-05-17 15
            2023-05-24 13
            ")

# This groups the data by month and by an increase within a month
mydatatable <- data.table(mydata) %>%
  mutate(
    mnth = format(as.Date(data_date), format="%b"),  
    jumpup = as.character( cumsum( ifelse( c(-1, diff(mydata$data_value) ) > 0 , 1, 0 )  ) ) , 
    month_jumpup = as.factor( paste(mnth, jumpup ) ) ,
    data_date = as.POSIXct(data_date, format="%Y-%m-%d", tz="UTC") ) %>%
  select(data_date, data_value, month_jumpup) 

# Linear regression to extract slope of the line of each group
fm1 <- lmList(data_value ~ data_date | month_jumpup , mydatatable)

# tibble with daily rate/slope per group 
ratetib <- tibble(month_jumpup = names(fm1),
                  rateperday = as.factor( round( -24*3600*summary(fm1)$coef[,1,2], 3 ) ) )

plottib <- tibble(mydatatable) %>%
    left_join(ratetib, by = c("month_jumpup" = "month_jumpup")) 

gm <- ggplot( plottib , aes( x=data_date, y=data_value, color=rateperday )) +
  geom_point() +
  geom_smooth( method="lm", se=FALSE) 

gm

enter image description here


Solution

  • You can reorder your factor using fct_inorder:

    gm <- ggplot( plottib , aes( x=data_date, y=data_value, color=fct_inorder(rateperday) )) +
      geom_point() +
      geom_smooth( method="lm", se=FALSE) 
    
    gm
    #> `geom_smooth()` using formula = 'y ~ x'