Problem: Override legend aesthetics. I want the Bev/Steroid legend to show up as a line with the relevant color (as it is now) and the background to be white/null. Then I want the On/Off Study and Response Legends to be the standard rectangle with relevant coloring. I would also like to re-order the legends to be 1. On/Off --> 2. Response --> 3. Bev/Steroids, but this is more of a bonus.
Background: Working with 5 datasets. On/Off dataset for the first geom_segment layer for the length on study and time the subject was alive and off study; Response dataset to mark whether patients had stable disease, partial response, or complete response; Dose information to add geom_point upside down triangles where patients were dosed (geom_label of actual dose removed for example due to potential sensitive info); Bev/Steroid use datasets, these are the geom_segment are on the edges of the On/Off geom_segment.
Steps Taken: Attempted to set key_glyph = "rect" for On/Off and Response legends and key_glyph = "smooth" for the steroid/bev legend. I have attempted many combinations of guide_legend, but to no avail.
Data: 5 different datasets are used in this plot:
- Response dataset: response
tibble [127 x 4] (S3: tbl_df/tbl/data.frame)
$ SUBJECT : chr [1:127] "01" "01" "01" "01" ...
$ RESPONSE : chr [1:127] "Stable Disease" "Partial Response" "Complete Response" "Progressive Disease" ...
$ STARTRESP: num [1:127] 0 9.23 21.03 62.03 0 ... #continuous start stop time in months
$ ENDRESP : num [1:127] 9.23 21.03 62.03 88 1.9 ...
# A tibble: 6 x 4
SUBJECT RESPONSE STARTRESP ENDRESP
<chr> <chr> <dbl> <dbl>
1 01 Stable Disease 0 9.23
2 01 Partial Response 9.23 21.0
3 01 Complete Response 21.0 62.0
4 01 Progressive Disease 62.0 88
5 02 Stable Disease 0 1.9
6 02 Progressive Disease 1.9 93.6
- On/Off Dataset: onoff
'data.frame': 112 obs. of 6 variables:
$ SUBJECT : chr "01" "01" "02" "02" ...
$ RESPONSE : chr "On Study" "Off Study/Alive" "On Study" "Off Study/Alive" ...
$ STARTRESP: num 0 88.9 0 93.6 0 ...
$ ENDRESP : num 88.9 94.48 93.58 93.81 4.13 ...
$ ALIVE : num 0 0 0 0 0 0 0 0 0 0 ... #binary flag to indicate whether subject still alive; used for subsetting
$ MAX_RESP : num 94.48 94.48 93.81 93.81 5.77 ... #overall survival used for subsetting
SUBJECT RESPONSE STARTRESP ENDRESP ALIVE MAX_RESP
1 01 On Study 0.000000 88.900000 0 94.483871
2 01 Off Study/Alive 88.900000 94.483871 0 94.483871
3 02 On Study 0.000000 93.580645 0 93.806452
4 02 Off Study/Alive 93.580645 93.806452 0 93.806452
5 03 On Study 0.000000 4.129032 0 5.774194
6 03 Off Study/Alive 4.129032 5.774194 0 5.774194
- Dose Info Dataset: dose
$ SUBJECT : chr [1:67] "01" "01" "02" "02" ...
$ TREATMENT: Factor w/ 7 levels #redacted
$ DATE : POSIXct[1:67], format: #redacted
$ DUR : num [1:67] 0 71 0 59 77 0 0 0 0 0 ... #continuous months duration
- Bev Use Dataset: bev
tibble [140 x 5] (S3: tbl_df/tbl/data.frame)
$ SUBJECT : chr [1:140] "01" "01" "01" "02" ...
$ ORD : num [1:140] 1 2 3 1 1 1 2 3 1 2 ...
$ BEV : chr [1:140] "Bevacizumab" "Bevacizumab" "Bevacizumab" "Bevacizumab" ...
$ STARTBEV: num [1:140] 81.48 89.34 93.91 87.7 4.44 ...
$ ENDBEV : num [1:140] 88.91 93.42 93.91 88.36 4.87 ...
- Steroid Use Dataset: steroid
$ SUBJECT : chr [1:668] "01" "01" "01" "01" ...
$ ORD : num [1:668] 1 2 3 4 5 6 7 8 9 10 ...
$ STARTROIDS: num [1:668] 1 1 1 1 1 ...
$ ENDROIDS : num [1:668] 1 1 1 1 1 ...
$ STEROIDS : chr [1:668] "Steroids" "Steroids" "Steroids" "Steroids" ...
Edit 1: Example datasets added
#onoff dataset
#most subjects will have 2 entries (1. on study/2. off study/alive), unless they passed while on study
SUBJECT <- c("01", "01", "02", "02", "03", "03", "04","04", "05", "05")
RESPONSE <- c("On Study", "Off Study/Alive", "On Study", "Off Study/Alive", "On Study", "Off Study/Alive", "On Study", "Off Study/Alive", "On Study", "Off Study/Alive")
STARTRESP <- c(0, 50, 0, 25, 0, 5, 0, 12, 0, 22)
ENDRESP <- c(50, 70, 25, 50, 5, 10, 12, 18, 22, 35)
ALIVE <- c(0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
onoff <- data.frame(SUBJECT, RESPONSE, STARTRESP, ENDRESP, ALIVE)
#response dataset
#response should generally occur during the "on study" period
SUBJECT <- c("01", "01", "01", "01", "02", "02", "03", "03", "04", "05", "05", "05")
RESPONSE <- c("Stable Disease", "Partial Response", "Complete Response", "Progressive Disease", "Stable Disease", "Partial Response", "Progressive Disease", "Stable Disease", "Progressive Disease", "Stable Disease", "Progressive Disease", "Stable Disease", "Partial Response", "Complete Response", "Progressive Disease")
STARTRESP <- c(0, 4, 8, 48, 0, 6, 24, 0, 4, 0, 11, 0, 6, 13, 18)
ENDRESP <- c(4, 8, 48, 50, 6, 24, 25, 4, 5, 11, 12, 6, 13, 18, 22)
response <- data.frame(SUBJECT, RESPONSE, STARTRESP, ENDRESP)
#steroids dataset
#not all subjects get steroids
SUBJECT <- c("01", "01", "04")
STARTROIDS <- c(10, 56, 4)
ENDROIDS <- c(18, 68, 10)
STEROIDS <- c("Steroids", "Steroids", "Steroids")
steroids <- data.frame(SUBJECT, STARTROIDS , ENDROIDS, STEROIDS)
#bev dataset
#not all subjects get bev
SUBJECT <- c("01", "01", "04")
STARTBEV <- c(12, 60, 6)
ENDBEV <- c(18, 70, 10)
BEV <- c("Bevacizumab", "Bevacizumab", "Bevacizumab")
bev <- data.frame(SUBJECT, STARTBEV , ENDBEV, BEV)
#dose dataset
#added repeat dosing and different levels to make comparable to real world data
SUBJECT <- c("01", "01", "02", "03", "04", "05", "05")
TREATMENT <- c(50000, 10000, 12000, 10000, 10000, 50000)
DUR <- c(0, 12, 0, 0, 0, 34)
dose <- data.frame(SUBJECT, TREATMENT, DUR)
Code:
#Prespecified color palettes
response_color <- c("Stable Disease" = "gold",
"Partial Response" = "blue2",
"Complete Response" = "green4",
"Progressive Disease" = "red1")
onoff_study_color <- c("On Study" = "lightblue",
"Off Study/Alive" = "gray75")
steroidbev_color <- c("Steroids" = "orangered",
"Bevacizumab" = "mediumorchid4")
#ggplot code
ggplot() +
theme_classic() +
scale_colour_manual(name = "On/Off Study", values = onoff_study_color) +
geom_vline(xintercept = 6, colour = "gray69", linetype = "longdash",
show.legend = FALSE) +
geom_segment(data = onoff, aes(x = STARTRESP, xend = ENDRESP,
y = SUBJECT, yend = SUBJECT,
colour = RESPONSE),
size = 5, show.legend = TRUE,
key_glyph = "label") +
new_scale_color() + #from the 'ggnewscale' package
scale_colour_manual(name = "Response", values = response_color) +
geom_segment(data = response, aes(x = STARTRESP, xend = ENDRESP,
y = SUBJECT, yend = SUBJECT,
colour = RESPONSE),
size = 2, show.legend = TRUE,
key_glyph = "label") +
geom_point(data = response, aes(x = STARTRESP, y = SUBJECT,
colour = RESPONSE),
shape = 21, size = 2.5, fill = "white", show.legend = FALSE) +
geom_point(data = response, aes(x = ENDRESP, y = SUBJECT,
colour = RESPONSE),
shape = 21, size = 2.5, fill = "white", show.legend = FALSE) +
new_scale_color() + #from the 'ggnewscale' package
scale_colour_manual(name = "Steroid/Bevacizumab Use", values = steroidbev_color) +
geom_segment(data = steroids, aes(x = STARTROIDS, xend = ENDROIDS,
y = SUBJECT, yend = SUBJECT,
colour = STEROIDS),
size = 1, position = position_nudge(y = 0.15), linetype = 1, show.legend = TRUE,
key_glyph = "smooth") +
geom_segment(data = bev, aes(x = STARTBEV, xend = ENDBEV,
y = SUBJECT, yend = SUBJECT,
colour = BEV),
size = 1, position = position_nudge(y = -0.15), linetype = 1, show.legend = TRUE) +
geom_point(data = dose, aes(x = DUR, y = SUBJECT,
fill = TREATMENT),
shape = 25, size = 4, position = position_nudge(y = 0.2), show.legend = FALSE) +
labs(title = "Example Swims",
caption = "Subjects with OS of >18 mos.; Arrow indicates subject is still alive") +
scale_x_continuous(name = "Duration in Months", breaks = seq(0,90,10)) +
ylab(label = "Subject ID") +
scale_fill_discrete() +
geom_text(aes(x=DUR, y=SUBJECT, label = TREATMENT), data = dose,
nudge_y = 0.4, nudge_x = 0, size = 3) +
theme(legend.key = element_rect(fill = "white", colour = "white")) +
guides(fill = FALSE)
Resulting plot:
Edit 2: Code using gtable:
I tried to revise the code using gtable, which I am not familiar with. I was able to get the legend formatted the way that I wanted, however, now the layers are messed up and the legend is smack dab in the middle of the plot. Any advice on how to properly layer and reposition the legend?
p1 <- ggplot() +
theme_classic() +
scale_colour_manual(name = "On/Off Study", values = onoff_study_color,
guide_legend(override.aes = list(color = onoff_study_color,
fill = onoff_study_color,
alpha = 1,
shape = 22))) +
theme(legend.key = element_rect(fill = "white", colour = "white")) +
geom_vline(xintercept = 6, colour = "gray69", linetype = "longdash",
show.legend = FALSE) +
geom_segment(data = subj_18mos_onoff, aes(x = STARTRESP, xend = ENDRESP,
y = SUBJECT, yend = SUBJECT,
colour = RESPONSE),
size = 5, show.legend = TRUE) +
labs(title = "Phase 1 GBM Swim Plots",
subtitle = "Data from study Pro00031169",
caption = "Subjects with OS of >18 mos.; Arrow indicates subject is still alive") +
scale_x_continuous(name = "Duration in Months", breaks = seq(0,90,10)) +
ylab(label = "Subject ID")
#new_scale_color() +
p2 <- ggplot() +
theme_classic() +
scale_colour_manual(name = "Response", values = response_color,
guide = guide_legend(override.aes = list(color = response_color,
fill = response_color,
alpha = 1,
shape = 22))) +
geom_segment(data = subj_18mos_resp, aes(x = STARTRESP, xend = ENDRESP,
y = SUBJECT, yend = SUBJECT,
colour = RESPONSE),
size = 2, show.legend = TRUE) +
geom_point(data = subj_18mos_resp, aes(x = STARTRESP, y = SUBJECT,
colour = RESPONSE),
shape = 21, size = 2.5, fill = "white", show.legend = FALSE) +
geom_point(data = subj_18mos_resp, aes(x = ENDRESP, y = SUBJECT,
colour = RESPONSE),
shape = 21, size = 2.5, fill = "white", show.legend = FALSE)
#new_scale_color() +
p3 <- ggplot() +
theme_classic() +
scale_colour_manual(name = "Steroid/Bevacizumab Use", values = steroidbev_color,
guide = guide_legend(override.aes = list(color = steroidbev_color,
fill = steroidbev_color,
alpha = 1,
shape = 95,
size = 1.5))) +
geom_segment(data = subj_18mos_steroids, aes(x = STARTROIDS, xend = ENDROIDS,
y = SUBJECT, yend = SUBJECT,
colour = STEROIDS),
size = 1, position = position_nudge(y = 0.15), linetype = 1, show.legend = TRUE) +
geom_segment(data = subj_18mos_bev, aes(x = STARTBEV, xend = ENDBEV,
y = SUBJECT, yend = SUBJECT,
colour = BEV),
size = 1, position = position_nudge(y = -0.15), linetype = 1, show.legend = TRUE) +
geom_point(data = subj_18mos_dose, aes(x = DUR, y = SUBJECT,
fill = TREATMENT),
shape = 25, size = 4, position = position_nudge(y = 0.2), show.legend = FALSE) +
scale_fill_discrete() +
geom_text(aes(x=DUR, y=SUBJECT, label = TREATMENT), data = subj_18mos_dose,
nudge_y = 0.4, nudge_x = 0, size = 3) +
guides(fill = FALSE)
#extract gtables
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
g3 <- ggplotGrob(p3)
#get legends
leg1 = g1$grobs[[which(g1$layout$name == "guide-box")]]
leg2 = g2$grobs[[which(g2$layout$name == "guide-box")]]
leg3 = g3$grobs[[which(g3$layout$name == "guide-box")]]
# Join them into one legend
leg = rbind(leg1, leg2, leg3, size = "first")
# Drop the legends from the two gtables
pos = subset(g1$layout, grepl("guide-box", name), l)
g1 = g1[, -pos$l]
g2 = g2[, -pos$l]
g3 = g3[, -pos$l]
# Get the location of the plot panel in g1.
# These are used later when transformed elements of g2 are put back into g1
pp <- c(subset(g1$layout, name == "panel", se = t:r))
#pp2 <- c(subset(g2$layout, name == "panel", se = t:r))
#pp3 <- c(subset(g3$layout, name == "panel", se = t:r))
# Overlap panel for second plot on that of the first plot
g1 <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "panel")]], pp$t, pp$l, pp$b, pp$l)
g1 <- gtable_add_grob(g1, g3$grobs[[which(g3$layout$name == "panel")]], pp$t, pp$l, pp$b, pp$l)
grid.draw(g1)
grid.draw(leg)
SwimmerPlot_18mos_full <- grid.grab()
SwimmerPlot_18mos_full
#ggsave("SwimmerPlot_18mos_full.png", plot = SwimmerPlot_18mos_full, width = 10,
# height = 10, dpi = 320)

