How can I reorder the legend in ggplot2 having scale_colour_manual and scale_linetype_manual together?

Viewed 293

I need to change the order in the ggplot legend. A simple plot for this purpose is copied below. How can I have 'Forecaster_2' appear before 'Forecaster_1'? I have tried breaks but could not make it work.

library(ggplot2)

x_1 <- rep(0:6, each = 2)
pdf_1 <- c(0,0.05,0.05,0.1,0.1,0.15,0.15,0.3,0.3,0.25,0.25,0.15,0.15,0)

x_2 <- rep(3:9, each = 2)
pdf_2 <- c(0,0.05,0.05,0.1,0.1,0.15,0.15,0.3,0.3,0.25,0.25,0.15,0.15,0)

data_1 <- data.frame(x_1, pdf_1,x_2,pdf_2)

ggplot()+
  geom_line(data=data_1,aes(x=x_1, y=pdf_1, color="Forecaster_1", linetype='Forecaster_1'),size=1)+
  geom_line(data=data_1,aes(x=x_2, y=pdf_2, color="Forecaster_2", linetype='Forecaster_2'),size=1)+
  labs(x = "x") +
  labs(y = "PDF") +
  scale_colour_manual("Line", values = c('Forecaster_1' = 'cornflowerblue', 'Forecaster_2' = 'coral2')) +
  scale_linetype_manual("Line", values = c('Forecaster_1' = 'solid', 'Forecaster_2' = 'dashed'))+
  theme(legend.position="top",
        legend.title=element_blank())
3 Answers

edit:

library(tidyverse)
df<-data_1 %>%
  pivot_longer(everything(),
               names_to = c(".value", "group"),
               names_sep = "_"
  ) %>% 
  mutate(
    group = factor(group, levels = c(2,1), 
                   labels =  c('Forecater_2', 'Forcaster_1')))

df %>% 
  ggplot(aes(x= x, y = pdf, color=group, linetype = group))+
  geom_line() +
  theme(legend.position="top",
        legend.title=element_blank())

enter image description here

I would reshape the data in order to have a tidy format.

A straightforward way to do this would be to select x_1 and pdf_1 and bind rows over x_2 and pdf_2, but if you have more than two series, this can be a tedious approach. So, i suggest usign pivot_longer and pivot_widerto do it.

library(dplyr)
library(tidyr)
library(ggplot2)
library(tibble)

data_long <- data_1 %>% 
    # important to avoid  common error by duplicates ids
    tibble::rowid_to_column() %>% 
    tidyr::pivot_longer(
        cols = -rowid, 
        names_to = "serie", 
        values_to = "values") %>% 
    tidyr::separate(serie, into = c("variable", "forecaster")) %>% 
    tidyr::pivot_wider(names_from = variable, values_from = values) %>%
    # This step is inportant, your legend will appear given the order
    # of the level argument
    dplyr::mutate(
        forecaster = factor(forecaster,
                            levels = c(2, 1),
                            labels = c("Forecaster 2", "Forecaster 1"))
        )

head(data_long)

# # A tibble: 6 x 3
#   forecaster       x   pdf
#   <fct>        <dbl> <dbl>
# 1 Forecaster 1     0  0   
# 2 Forecaster 2     3  0   
# 3 Forecaster 1     0  0.05
# 4 Forecaster 2     3  0.05
# 5 Forecaster 1     1  0.05
# 6 Forecaster 2     4  0.05

With your data that way, creating the plot is easier:

data_long %>% 
    ggplot(aes(x = x, y = pdf, linetype = forecaster, color = forecaster)) +
    geom_line(size = 1) +
    theme(legend.position = "top",
          legend.title = element_blank()) +
    scale_linetype_manual(values = c(2, 3)) +
    scale_color_manual(values = c("blue", "black"))

enter image description here

You can swap control the order for the legend by using guide = guide_legend(reverse=TRUE)is the scale definitions.

data_1 <- structure(list(x_1 = c(0L, 0L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L), 
                         pdf_1 = c(0, 0.05, 0.05, 0.1, 0.1, 0.15, 0.15, 0.3, 0.3, 0.25, 0.25, 0.15, 0.15, 0), 
                         x_2 = c(3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L), 
                         pdf_2 = c(0, 0.05, 0.05,0.1, 0.1, 0.15, 0.15, 0.3, 0.3, 0.25, 0.25, 0.15, 0.15, 0)), 
                    class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                              -14L))

ggplot()+
   geom_line(data=data_1,aes(x=x_1, y=pdf_1, color="Forecaster_1", linetype='Forecaster_1'),size=1)+
   geom_line(data=data_1,aes(x=x_2, y=pdf_2, color="Forecaster_2", linetype='Forecaster_2'),size=1)+
   labs(x = "x") +
   labs(y = "PDF") +
   scale_colour_manual("Line", values = c('Forecaster_1' = 'cornflowerblue', 'Forecaster_2' = 'coral2'), guide=guide_legend(reverse=TRUE)) +
   scale_linetype_manual("Line", values = c('Forecaster_1' = 'solid', 'Forecaster_2' = 'dashed'), guide=guide_legend(reverse=TRUE))+
   theme(legend.position="top",
         legend.title=element_blank())

enter image description here

Related