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_manual
part? 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)