r - Perfect fit of ggplot2 plot in plot -
i want plot restricted cubic spline main plot , add box-and-whisker plot show variation of x variable. however, lower hinge (x=42), median (x=51), , upper hinge(x=61) did not fit corresponding grid line of main plot.
library(hmisc) library(rms) library(ggplot2) library(gridextra) data(pbc) d <- pbc rm(pbc) d$status <- ifelse(d$status != 0, 1, 0) dd = datadist(d) options(datadist='dd') f <- cph(surv(time, status) ~ rcs(age, 4), data=d) p <- predict(f, fun=exp) df <- data.frame(age=p$age, yhat=p$yhat, lower=p$lower, upper=p$upper) ### 1st plot: main plot (g <- ggplot(data=df, aes(x=age, y=yhat)) + geom_line(size=1)) # ci (g <- g + geom_ribbon(data=df, aes(ymin=lower, ymax=upper), alpha=0.5, linetype=0, fill='#ffc000')) # white background (g <- g + theme_bw()) # x-axis (breaks <- round(boxplot.stats(p[,"age"])$stats)) (g <- g + scale_x_continuous(breaks=breaks, limits=range(p[,"age"]), labels=round(breaks))) (g <- g + xlab("age")) # y-achse (g <- g + ylab("hazard ratio")) # size , color of axis (g <- g + theme(axis.line = element_line(color='black', size=1))) (g <- g + theme(axis.ticks = element_line(color='black', size=1))) (g <- g + theme( plot.background = element_blank() )) #(g <- g + theme( panel.grid.major = element_blank() )) (g <- g + theme( panel.grid.minor = element_blank() )) (g <- g + theme( panel.border = element_blank() )) ### 2nd plot: box whisker plot describe(df$age, digits=0) round(range(df$age)) (gg <- ggplot(data=df, aes(x=1, y=age)) + geom_boxplot(outlier.shape=na, size=1) + coord_flip()) (gg <- gg + theme( axis.line=element_blank() )) # (gg <- gg + theme( axis.text.x=element_blank() )) (gg <- gg + theme( axis.text.y=element_blank() )) (gg <- gg + theme( axis.ticks=element_blank() )) (gg <- gg + theme( axis.title.x=element_blank() )) (gg <- gg + theme( axis.title.y=element_blank() )) (gg <- gg + theme( panel.background=element_blank() )) (gg <- gg + theme( panel.border=element_blank() )) # (gg <- gg + theme( legend.position="none" )) # (gg <- gg + theme( panel.grid.major=element_blank() )) # (gg <- gg + theme( panel.grid.minor=element_blank() )) (gg <- gg + theme( plot.background=element_blank() )) (gg <- gg + theme( plot.margin = unit( c(0,0,0,0), "in" ) )) (gg <- gg + scale_x_continuous(breaks=c(70,77,84), expand=c(0,0)) ) ### final plot: put box whisker plot in main plot (final.gg <- g + annotation_custom(ggplotgrob(gg), ymin=2.4, ymax=2.6))
- what have change perfect fit?
- is there better automatized alignment of y-position of box-and-whisker?
update #1 answer! below can see example code. however, can see, lower hinge, median, , upper hinge still not fit. going wrong?
library(hmisc) library(rms) library(ggplot2) library(gridextra) data(pbc) d <- pbc rm(pbc, pbcseq) d$status <- ifelse(d$status != 0, 1, 0) dd = datadist(d) options(datadist='dd') f <- cph(surv(time, status) ~ rcs(age, 4), data=d) p <- predict(f, fun=exp) df <- data.frame(age=p$age, yhat=p$yhat, lower=p$lower, upper=p$upper) ### 1st plot: main plot (breaks <- boxplot.stats(p[,"age"])$stats) g <- ggplot(data=df, aes(x=age, y=yhat)) + geom_line(size=1) + geom_ribbon(data=df, aes(ymin=lower, ymax=upper), alpha=0.5, linetype=0, fill='#ffc000') + theme_bw() + scale_x_continuous(breaks=breaks) + xlab("age") + ylab("hazard ratio") + theme(axis.line = element_line(color='black', size=1), axis.ticks = element_line(color='black', size=1), plot.background = element_blank(), # panel.border = element_blank(), panel.grid.minor = element_blank()) ### 2nd plot: box whisker plot gg <- ggplot(data=df, aes(x=1, y=age)) + geom_boxplot(outlier.shape=na, size=1) + scale_y_continuous(breaks=breaks) + ylab(null) + coord_flip() + # theme_bw() + theme(axis.line=element_blank(), # axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks.y=element_blank(), axis.title=element_blank(), # panel.background=element_blank(), panel.border=element_blank(), # panel.grid.major=element_blank(), panel.grid.minor=element_blank(), # plot.background=element_blank(), plot.margin = unit( c(0,0,0,0), "in" ), axis.ticks.margin = unit(0, "lines"), axis.ticks.length = unit(0, "cm")) ### final plot: put box whisker plot in main plot (final.gg <- g + annotation_custom(ggplotgrob(gg), ymin=2.4, ymax=2.6))
minor edit: updating ggplot2 2.0.0 axis.ticks.margin
deprecated
in boxplot, though have set various elements element_blank
, margins zero, default spaces remain resulting in misalignment. these spaces belong to:
- axis.ticks.length
- xlab
in code below, i've re-arranged code (i hope that's okay), , commented out lines of code can seen 2 plots align. i've set breaks in 2 plot un-rounded breaks
(min , max values, hinges, , median).
# x-axis (breaks <- boxplot.stats(p[,"age"])$stats) ### 1st plot: main plot g <- ggplot(data=df, aes(x=age, y=yhat)) + geom_line(size=1) + geom_ribbon(data=df, aes(ymin=lower, ymax=upper), alpha=0.5, linetype=0, fill='#ffc000') + theme_bw() + scale_x_continuous(breaks=breaks) + xlab("age") + ylab("hazard ratio") + theme(axis.line = element_line(color='black', size=1), axis.ticks = element_line(color='black', size=1), plot.background = element_blank(), # panel.border = element_blank(), panel.grid.minor = element_blank()) ### 2nd plot: box whisker plot gg <- ggplot(data=df, aes(x=1, y=age)) + geom_boxplot(outlier.shape=na, size=1) + scale_y_continuous(breaks=breaks) + xlab(null) + coord_flip() + # theme_bw() + theme(axis.line=element_blank(), # axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks.y=element_blank(), axis.title=element_blank(), # panel.background=element_blank(), panel.border=element_blank(), # panel.grid.major=element_blank(), panel.grid.minor=element_blank(), # plot.background=element_blank(), plot.margin = unit( c(0,0,0,0), "in" ), # axis.ticks.margin = unit(0, "lines"), axis.ticks.length = unit(0, "cm")) ### final plot: put box whisker plot in main plot (final.gg <- g + annotation_custom(ggplotgrob(gg), ymin=2.4, ymax=2.6))
you should note ggplot's method calculating hinges differs method used boxplot.stats
.
# ggplot's hinges bp = ggplot(data=df, aes(x=1, y=age)) + geom_boxplot(outlier.shape=na, size=1) bpdata = ggplot_build(bp) bpdata$data[[1]][1:5]
Comments
Post a Comment