Home > OS >  how to add conditional statement when doing double legend
how to add conditional statement when doing double legend

Time:12-10

I try to make a plot with legend for both horizontal lines and vertical lines. Now I would like to test out whether I can add if statement base on the event status.

For the df with both Delay and Sick, my codes works. But if I want to modify the my plotting part so I can use it on a df that might only have Delay or Sick, what should I with my geom_vline and scale_linetype_manualpart? for example, if I want to use my codes on df2.


df<-structure(list(Day = c(0L, 0L, 0L, 1L, 1L, 1L, 8L, 8L, 8L, 15L, 
15L, 15L, 22L, 22L, 22L, 27L, 29L, 29L, 29L, 36L, 36L, 36L, 43L, 
43L, 43L, 43L, 43L, 43L), Subject = c("ELA", "Math", "Art", "Math", 
"Art", "ELA", "ELA", "Math", "Art", "ELA", "Math", "Art", "ELA", 
"Math", "Art", NA, "ELA", "Math", "Art", "ELA", "Math", "Art", 
"Art", "Art", "Math", "Math", "ELA", "ELA"), Score = c(73L, 157L, 
75L, 111L, 82L, 69L, 78L, 131L, 93L, 58L, 109L, 99L, 79L, 131L, 
84L, NA, 67L, 106L, 90L, 75L, 123L, 95L, 122L, 122L, 137L, 137L, 
83L, 83L), Event = c(NA, NA, NA, "Delay", "Delay", "Delay", NA, 
NA, NA, NA, NA, NA, NA, NA, NA, "Sick", NA, NA, NA, NA, NA, NA, 
"Sick", "Delay", "Sick", "Delay", "Sick", "Delay")), class = "data.frame", row.names = c(NA, 
-28L))

ggplot(data =df) 
    geom_line(data=df[!is.na(df$Score),],aes(x = Day, y = Score, color=Subject),size=0.8) 
        scale_colour_manual(breaks = c("ELA", "Math", "Art"),
                        values=c(ELA="#cc0022",Math="#70ad47", Art="#fd9300")) 
    geom_vline(data=df[(!is.na(df$Event)&df$Event=="Delay"),], aes(xintercept=jitter(Day), linetype="Delay"), color="black", size=0.4) 
geom_vline(data=df[(!is.na(df$Event)&df$Event=="Sick"),], aes(xintercept=jitter(Day), linetype="Sick"), color="purple", size=0.4) 
scale_linetype_manual(name = 'Event',
                        values = c('Delay' = 1,
                                   'Sick' = 1),
                        guide = guide_legend(override.aes = list(colour = c("black",
                        "purple"))))

df2 <-structure(list(Day = c(0L, 0L, 0L, 1L, 1L, 1L, 8L, 8L, 8L, 15L, 
15L, 15L, 22L, 22L, 22L, 27L, 29L, 29L, 29L, 36L, 36L, 36L, 43L, 
43L, 43L, 43L, 43L, 43L), Subject = c("ELA", "Math", "Art", "Math", 
"Art", "ELA", "ELA", "Math", "Art", "ELA", "Math", "Art", "ELA", 
"Math", "Art", NA, "ELA", "Math", "Art", "ELA", "Math", "Art", 
"Art", "Art", "Math", "Math", "ELA", "ELA"), Score = c(73L, 157L, 
75L, 111L, 82L, 69L, 78L, 131L, 93L, 58L, 109L, 99L, 79L, 131L, 
84L, NA, 67L, 106L, 90L, 75L, 123L, 95L, 122L, 122L, 137L, 137L, 
83L, 83L), Event = c(NA, NA, NA, "Delay", "Delay", "Delay", NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, "Delay", NA, "Delay")), class = "data.frame", row.names = c(NA, 
-28L))

I am thinking using sth like this (they don't work)

df<-df2
ggplot(data =df) 
    geom_line(data=df[!is.na(df$Score),],aes(x = Day, y = Score, color=Subject),size=0.8) 
        scale_colour_manual(breaks = c("ELA", "Math", "Art"),
                        values=c(ELA="#cc0022",Math="#70ad47", Art="#fd9300")) 
   {if (grepl("Delay", df$Event)) geom_vline(data=df[(!is.na(df$Event)&df$Event=="Delay"),], aes(xintercept=jitter(Day), linetype="Delay"), color="black", size=0.4)} 
   {if (grepl("Sick", df$Event)) geom_vline(data=df[(!is.na(df$Event)&df$Event=="Sick"),], aes(xintercept=jitter(Day), linetype="Sick"), color="purple", size=0.4)} 
scale_linetype_manual(name = 'Event',
                        values = c('Delay' = 1,
                                   'Sick' = 1),
                        guide = guide_legend(override.aes = list(colour = c("black",
                        "purple"))))

Code chunk 3:

ggplot(data =df) 
    geom_line(data=df[!is.na(df$Score),],aes(x = Day, y = Score, color=Subject),size=0.8) 
        scale_colour_manual(breaks = c("ELA", "Math", "Art"),
                        values=c(ELA="#cc0022",Math="#70ad47", Art="#fd9300")) 
 geom_vline(data=df[(!is.na(df$Event)&df$Event=="Delay"),], aes(xintercept=jitter(Day),linetype="Delay"), color="black", size=0.4) 
# geom_vline(data=df[(!is.na(df$Event)&df$Event=="Sick"),], aes(xintercept=jitter(Day) ), color="purple", size=0.4) 
scale_linetype_manual(name = 'Event',
                      values = c(
        "Delay" = 1,
        "Sick" = 1
      ),
                        guide = guide_legend(override.aes = list(colour = c("black",
                        "purple"))))

CodePudding user response:

With using an if to add the layers you are on the right track. Instead of putting the conditions inside the ggplot code personally I prefer to setup the conditional layers outside of ggplot code and best to put everything inside a function.

Doing so, one option to achieve your desired result may look like so:

EDIT Additionally, instead of using the hack via the linetype aes to get a separate legend you could use the ggnewscale package to add a second color legend. One benefit is that we need no fiddling via override.aes and no additional conditioning to manage the different cases:

library(ggplot2)

plot_fun <- function(df) {
  is_delay <- !is.na(df$Event) & df$Event == "Delay"
  is_sick <- !is.na(df$Event) & df$Event == "Sick"
  
  layer_delay <- if (any(is_delay)) geom_vline(data = df[is_delay, ], aes(xintercept = jitter(Day), color = "Delay"), size = 0.4)
  layer_sick <- if (any(is_sick)) geom_vline(data = df[is_sick, ], aes(xintercept = jitter(Day), color = "Sick"), size = 0.4)
  
  ggplot(data = df)  
    geom_line(data = df[!is.na(df$Score), ], aes(x = Day, y = Score, color = Subject), size = 0.8)  
    scale_colour_manual(
      breaks = c("ELA", "Math", "Art"),
      values = c(ELA = "#cc0022", Math = "#70ad47", Art = "#fd9300"),
    )  
    ggnewscale::new_scale_color()  
    layer_delay  
    layer_sick  
    scale_colour_manual(
      name = "Event",
      values = c(Delay = "black", Sick = "purple"),
      limits = force
    )
}

plot_fun(df2)

  •  Tags:  
  • r
  • Related