【问题标题】:ggplot a panel of histograms with histograms as subplotsggplot 一组直方图,直方图作为子图
【发布时间】:2016-06-14 16:42:57
【问题描述】:

我在三个站点收集了数据,在每个站点中,这些数据针对多个受试者收集了多次。

数据如下所示:

set.seed(1)
df <- data.frame(site = c(rep("AA",1000),rep("BB",500),rep("CC",750)),
                 y = c(rnorm(1000,1,2),runif(500,1,3),rgamma(750,shape=1)))

#add subjects - using a function that randomly generates
#a number of subjects that adds up to their total at that site

site_a_subjects <- diff(c(0, sort(20*sample(19)), 1000))
site_b_subjects <- diff(c(0, sort(30*sample(9)), 500))
site_c_subjects <- diff(c(0, sort(40*sample(4)), 750))

#add these subjects
df$site_subjects <- c(unlist(sapply(1:20, function(x) rep(letters[x], site_a_subjects[x]))),
                  unlist(sapply(1:10, function(x) rep(letters[x], site_b_subjects[x]))),
                  unlist(sapply(1:5, function(x) rep(letters[x], site_c_subjects[x]))))

我想为每个站点绘制y 的直方图。 这条ggplot2 简单的线路很容易做到这一点:

ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="white") + facet_grid(. ~ site)

但是,我还想在每个站点直方图上绘制一个子图,它是该站点上每个主题观察次数的直方图。 比如添加:

hist(table(df$site_subjects[which(df$site == "AA")]))
hist(table(df$site_subjects[which(df$site == "BB")]))
hist(table(df$site_subjects[which(df$site == "CC")]))

分别到三个站点直方图。

知道怎么做吗?

我想知道是否可以调整 annotation_custom 来实现这一点?

此代码将起作用,但前提是:

ggplotGrob(ggplot(df, aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9))

command 可以接受 listggplot 对象或类似的东西。

这里是'几乎;解决方案: 首先弄清楚所有分面直方图中的最大条高度是多少

ymax <- max(sapply(unique(df$site), function(x) max(hist(df$y[which(df$site == x)],plot=FALSE)$counts)))

然后:

main.plot <- ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="gray") + facet_grid(~site) + scale_y_continuous(limits=c(0,1.2*ymax))
main.plot.info <- ggplot_build(main.plot)
xmin <- min(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)])
xmax <- max(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)])
main.plot <- main.plot + annotation_custom(grob = grid::roundrectGrob(),xmin = xmin, xmax = xmax, ymin=ymax, ymax=1.2*ymax)
sub.plot <- ggplotGrob(ggplot(df, aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9))
combined.plot <- main.plot +  annotation_custom(grob = sub.plot, xmin = xmin, xmax = xmax, ymin=ymax, ymax=1.2*ymax)

结果是:

【问题讨论】:

    标签: r ggplot2 grid subplot grob


    【解决方案1】:

    执行此操作的一种方法是创建主图,然后通过在您想要插入图的每个位置创建视口来添加每个插图。我们使用来自grid 包的函数来执行这些操作。这是一个例子:

    library(grid)
    
    # Function to draw the inset plots 
      pp = function(var) {
        grid.draw(
          ggplotGrob(
            ggplot(df[df$site==var,], aes(site_subjects)) +
              geom_bar() +
              theme_bw(base_size=9)
          )
        )
      }  
    
    # Function to place the viewports on the main graph
    my_vp = function(x) {
      viewport(x=x, y=.8, width=0.25, height=0.2)
    }
    
    # Main plot
    ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="white") + 
      facet_grid(. ~ site) +
      scale_y_continuous(limits=c(0,400))
    
    # Draw each inset plot in a separate viewport
    vp = my_vp(0.22)
    pushViewport(vp)
    pp("AA")
    popViewport()
    
    vp = my_vp(0.52)
    pushViewport(vp)
    pp("BB")
    popViewport()
    
    vp = my_vp(0.84)
    pushViewport(vp)
    pp("CC")
    

    【讨论】:

    • 很好!!!有没有办法预先确定主图方面的 x 位置,以便可以将它们传递给 my_vp 而不是对值进行硬编码?
    • 另外,如何更改此代码以便将图形绘制到文件中?
    • 对于第二个问题,在开始主图之前执行tiff("myplot.tiff", 1000, 800)(或您想要的任何文件名和分辨率),然后在添加所有插图后执行dev.off()
    • 对于你的第一个问题,我确信有办法,但我对grid 和 ggplot 对象的底层结构的了解还不够深入,无法弄清楚出去。您可以尝试在ggplot2 google 群组中询问这个问题,或者希望@baptiste 看到这个问题并提供一些想法。
    【解决方案2】:

    这是合理的:

    ymax <- max(sapply(unique(df$site), function(x) max(hist(df$y[which(df$site == x)],plot=FALSE)$counts)))
    sites <- unique(df$site)
    plot.list <- sapply(sites, function(s) {
      main.plot = ggplot(df[which(df$site == s),], aes(x=y)) + geom_histogram(colour="black", fill="gray") + scale_y_continuous(limits=c(0,1.5*ymax))
      main.plot.info = ggplot_build(main.plot)
      xmin = min(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)])
      xmax = max(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)])
      sub.plot = ggplotGrob(ggplot(df[which(df$site == s),], aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9))
      return(ggplotGrob(main.plot + annotation_custom(grob = sub.plot, xmin = xmin, xmax = xmax, ymin=0.8*ymax, ymax=1.2*ymax)))})
    
    grid.arrange(grobs=plot.list, ncol=3)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      相关资源
      最近更新 更多