Annotate x-axis with N in faceted plot

梦想与她 提交于 2020-01-04 04:31:16

问题


I'm trying to produce a boxplot of some numeric outcome broken down by treatment condition and visit number, with the number of observations in each box placed under the plot, and the visit numbers labeled as well. Here's some fake data that will serve to illustrate, and I give two examples of things I've tried that didn't quite work.

library(ggplot2)
library(plyr)

trt      <- factor(rep(LETTERS[1:2],150),ordered=TRUE)
vis      <- factor(c(rep(1,150),rep(2,100),rep(3,50)),ordered=TRUE)
val      <- rnorm(300)
data     <- data.frame(trt,vis,val)
data.sum <- ddply(data, .(vis, trt), summarise,
            N=length(na.omit(val)))
mytheme  <- theme_bw() + theme(panel.margin = unit(0, "lines"), strip.background = element_blank())

The below code produces a plot that has N labels where I want them. It does this by grabbing summary data from an auxiliary dataset I created. However, I couldn't figure out how to also label visit on the x-axis (ideally, below the individual box labels), or to delineate visits visually in other ways (e.g. lines separating them into panels).

plot1    <- ggplot(data) + 
            geom_boxplot(aes(x=vis:trt,y=val,group=vis:trt,colour=trt), show.legend=FALSE) +
            scale_x_discrete(labels=paste(data.sum$trt,data.sum$N,sep="\n")) +
            labs(x="Visit") + mytheme

The plot below is closer to what I want than the one above, in that it has a nice hierarchy of treatments and visits, and a pretty format delineating the visits. However, for each panel it grabs the Ns from the first row in the summary data that matches the treatment condition, because it doesn't "know" that each facet needs to use the row corresponding to that visit.

plot2    <- ggplot(data) +     geom_boxplot(aes(x=trt,y=val,group=trt,colour=trt), show.legend=FALSE) +
            facet_wrap(~ vis, drop=FALSE, switch="x", nrow=1) +
            scale_x_discrete(labels=paste(data.sum$trt,data.sum$N,sep="\n")) +
            labs(x="Visit") + mytheme

回答1:


One workaround is to manipulate your dataset so your x variable is the interaction between trt and N.

Working off what you already have, you can add N to the original dataset via a merge.

test = merge(data, data.sum)

Then make a new variable that is the combination of trt and N.

test = transform(test, trt2 = paste(trt, N, sep = "\n"))

Now make the plot, using the new trt2 variable on the x axis and using scales = "free_x" in facet_wrap to allow for the different labels per facet.

ggplot(test) +     
    geom_boxplot(aes(x = trt2, y = val, group = trt, colour = trt), show.legend = FALSE) +
    facet_wrap(~ vis, drop = FALSE, switch="x", nrow = 1, scales = "free_x") +
    labs(x="Visit") + 
    mytheme 




回答2:


Since this functionality isn't built in a good work-around is grid.extra:

library(gridExtra)
p1    <- ggplot(data[data$vis==1,]) +     geom_boxplot(aes(x=trt,y=val,group=trt,colour=trt), show.legend=FALSE) +
  #facet_wrap(~ vis, drop=FALSE, switch="x", nrow=1) +
  scale_x_discrete(labels=lb[1:2]) + #paste(data.sum$trt,data.sum$N,sep="\n")
  labs(x="Visit") + mytheme

p2    <- ggplot(data[data$vis==2,]) +     geom_boxplot(aes(x=trt,y=val,group=trt,colour=trt), show.legend=FALSE) +
  #facet_wrap(~ vis, drop=FALSE, switch="x", nrow=1) +
  scale_x_discrete(labels=lb[3:4]) + #paste(data.sum$trt,data.sum$N,sep="\n")
  labs(x="Visit") + mytheme

p3    <- ggplot(data[data$vis==3,]) +     geom_boxplot(aes(x=trt,y=val,group=trt,colour=trt), show.legend=FALSE) +
  #facet_wrap(~ vis, drop=FALSE, switch="x", nrow=1) +
  scale_x_discrete(labels=lb[5:6]) + #paste(data.sum$trt,data.sum$N,sep="\n")
  labs(x="Visit") + mytheme


grid.arrange(p1,p2,p3,nrow=1,ncol=3) # fully customizable

Related: Varying axis labels formatter per facet in ggplot/R

You can also make them vertical or do other transformations:



来源:https://stackoverflow.com/questions/39006840/annotate-x-axis-with-n-in-faceted-plot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!