-->

Overlay different ggplot2 objects

2019-03-04 07:20发布

问题:

I have previously tried to ask for help but did not actually solve my problem. More info can be found here: (you can find the data-set here) https://stackoverflow.com/questions/51442502/survival-analysis-combining-survfit-and-ggplot-objects

Unfortunately I am unable to produce a solid example to post as my code is heavily based on external programs. I am positive though that my question can be answered regardless.

I reach a point where I create 2 ggplot2 objects that need to be combined to a single figure, one overlayed on top of the other.

Namely, one km.plot which is of class:

class(km.plot$plot)
1 "gg" "ggplot"

and two:

class(surv.plot)
1 "gg" "ggplot"

Both share same attributes

km.plot$plot

surv.plot

My question is how can I combine the resulting plots in a single plot? That is, to have both surv.plot and km.plot$plot overlayed over each other.

Following another user's suggestion of doing the following results in an error:

 km.plot$plot + surv.plot$layers[[1]]
 Error in FUN(X[[i]], ...) : object 'label' not found

I assume this error has to do with the following few lines

 > surv.plot$layers
 [[1]]
 mapping: y = ~mean, group = ~label, colour = ~label 
 geom_line: na.rm = FALSE
 stat_identity: na.rm = FALSE
 position_identity 

 ggplot(data, aes(x=t)) +
 geom_line(aes(y= mean, group= label, colour= label), size=1.5) +

but I also added, inherit.aes = FALSE but did not fix my issue.

I also checked:

> head(surv.plot)
$`data`
curve           t      mean        lci       uci label
1    weibull  0.00000000 1.0000000 1.00000000 1.0000000  Cabo
2    weibull  0.05514645 0.9995771 0.99816278 0.9999721  Cabo
3    weibull  0.11029289 0.9990793 0.99646259 0.9999098  Cabo
4    weibull  0.16543934 0.9985407 0.99479769 0.9998211  Cabo
5    weibull  0.22058579 0.9979715 0.99316001 0.9997176  Cabo



 > head(km.plot)
 $`plot`

 $`data.survplot`
 time n.risk n.event n.censor      surv    std.err     upper     lower
 1   0.4271047     79       0        1 1.0000000 0.00000000 1.0000000 1.0000000
 2   1.0841889     78       1        0 0.9871795 0.01290349 1.0000000 0.9625264
 3   1.3470226     77       1        0 0.9743590 0.01836796 1.0000000 0.9399054
 4   3.9753593     76       1        0 0.9615385 0.02264554 1.0000000 0.9197944
 5   4.0082136     75       1        0 0.9487179 0.02632491 0.9989527 0.9010094

I am baffled. I am almost certain that this can be done as both objects are basically identical in terms of structure so I see no reason why this cannot be done. But I have spent quite some time on it with no hope. I really hope somebody can direct me!

Thank you for taking the time to read this post

回答1:

This happens because the surv.plot layer contains mappings for a variable called label which is not included in the data for km.plot. You should be able to get around this by adding your surv.plot data as an argument to the geom rather than ggplot() when you create surv.plot. This way the data needed to draw the layer will "travel with" it.

We can illustrate this with simpler data. Let's first create a plot from data with only a few columns:

library(tidyverse)

df1 <- mtcars %>% 
  select(mpg, wt)

# This represents `km.plot`
(p <- ggplot(df1, aes(wt, mpg)) + geom_point())

Now we can try to add a layer that relies on columns not included in df1 to the previous plot:

df2 <- mtcars %>% 
  select(mpg, wt, cyl)

q1 <- ggplot(df2, aes(wt, mpg)) +
  geom_smooth(aes(color = factor(cyl)), method = "lm")

p + q1$layers[[1]]
#> Error in factor(cyl): object 'cyl' not found

q2 <- ggplot() +
  geom_smooth(data = df2, aes(wt, mpg, color = factor(cyl)), method = "lm")

p + q2$layers[[1]]

Created on 2018-07-23 by the reprex package (v0.2.0.9000).