每页图表数量为奇数时的marrangeGrob函数问题

3

我有一份图表清单,并且使用marrangeGrob来将多个图表放在一页上。这样每页会显示6个图表:

marrangeGrob(plots, nrow=3, ncol=2, top=NULL)

但是我需要每页5个图表(即左下角的图表区域留空)

以下是基于我的数据子集的可重现示例:

> CohData
     Name ScenID ScenName Year VarName Units value
1  Site01      0     Hind 2000     ANC ueq/L 28.23
2  Site02      0     Hind 2000     ANC ueq/L 35.34
3  Site03      0     Hind 2000     ANC ueq/L 31.73
4  Site04      0     Hind 2000     ANC ueq/L 54.21
5  Site05      0     Hind 2000     ANC ueq/L 28.23
6  Site01      1       BC 2020     ANC ueq/L 45.01
7  Site02      1       BC 2020     ANC ueq/L 32.86
8  Site03      1       BC 2020     ANC ueq/L 30.38
9  Site04      1       BC 2020     ANC ueq/L 53.01
10 Site05      1       BC 2020     ANC ueq/L 31.11
11 Site01      0     Hind 2000      pH        6.40
12 Site02      0     Hind 2000      pH        5.93
13 Site03      0     Hind 2000      pH        6.36
14 Site04      0     Hind 2000      pH        5.75
15 Site05      0     Hind 2000      pH        5.16
16 Site01      1       BC 2020      pH        6.63
17 Site02      1       BC 2020      pH        5.86
18 Site03      1       BC 2020      pH        6.33
19 Site04      1       BC 2020      pH        5.73
20 Site05      1       BC 2020      pH        5.23

library(ggplot2)
library(grid)
library(gridExtra)

## Iterate plots and write to PDF
pdf("plots.pdf")
plots <- list()
CohData_nohind <- subset(CohData, ScenID > 0)
stream_vars <- list("ANC", "pH")
for (i in unique(CohData_nohind$ScenID)){
  subdata1 <- subset(CohData_nohind, ScenID == i)
  ScenName <- unique(subdata1$ScenName)
  subdata1 <- subset(CohData, ScenID == i | ScenID == 0)
  for (j in stream_vars){
    subdata2 <- subset(subdata1, VarName == j)
    units <- unique(subdata2$Units)
    for (k in unique(subdata2$Name)){
      subdata3 <- subset(subdata2, Name == k)

      if (j=='ANC'){
        p <- ggplot(subdata3, aes(x = Year, y = value)) + geom_line() + expand_limits(y=c(0,100)) + 
          ggtitle(paste0(as.character(ScenName),":\n", as.character(k))) + ylab(paste0(j, " (", units, ")"))
        plots[[paste(i,j,k,sep="_")]] = p

      } else if (j=='pH'){
        p <- ggplot(subdata3, aes(x = Year, y = value)) + geom_line() + expand_limits(y=c(3,7)) +
          ggtitle(paste0(as.character(ScenName),":\n", as.character(k))) + ylab(paste0(j, " (", units, ")"))
        plots[[paste(i,j,k,sep="_")]] = p
      }
    }
  }
}
interleave <- function(x, y, after = 1){

  nx <- length(x)
  ny <- length(y)

  if((nx %% after) > 0) x <- rep(x, length.out=after * ceiling(nx / after))
  mx <- matrix(x, ncol = after, byrow=TRUE)
  my <- rep(y, length.out = nrow(mx))

  c(t(cbind(mx, my)))
}

x <- replicate(7, ggplot(), simplify=FALSE)
y <- replicate(3, nullGrob(), simplify=FALSE)

marrangeGrob(interleave(x,y,3), ncol=2, nrow=2)
dev.off()

我该如何调整这段代码,以便将每个“VarName”下的5个“Names”分别写入单独的页面?
3个回答

6

我已经添加了传递布局的选项,请告诉我是否有任何问题。

点此链接查看详情。

# devtools::install_github("baptiste/gridextra")
library(gridExtra)
library(grid)

gl <- lapply(seq_len(7), function(ii) grobTree(rectGrob(gp=gpar(fill=ii)), 
                                               textGrob(ii)))
marrangeGrob(gl, layout_matrix=matrix(c(1,2,3,NA), 2))

enter image description here


我在所有的for循环之后包含了这个函数,但是收到了错误信息Error in gtable_add_grob(gt, grobs, t = positions$t, b = positions$b, : Not all inputs have either length 1 or same length same as 'grobs',除了在最后一行中将gl更改为plots之外,是否还需要修改我的代码? - viridius
我猜你的图表列表长度与每页布局x页面数量不兼容(7个grobs打破了上面的例子)。我需要重新考虑一下策略,同时DWin的想法是一个很好的解决方法。 - baptiste
我没有从DWin那里看到任何东西。42-下面的建议适用于此示例,但不适用于完整列表中的200多个图。我将有几百个图表用于其他“VarName”列表。感谢您重新考虑这个问题。 - viridius
@viridius:baptiste记忆力很好。我曾经使用过SO用户名DWin。 - IRTFM

3
在第6和第12位置插入一个空的grob:
plots[7:11] <- plots[6:10]
plots[[6]] <- textGrob("")
plots[[12]] <- textGrob("")

 pdf("plots.pdf")
 marrangeGrob(plots, nrow=3, ncol=2, top=NULL)
 dev.off()

enter image description here


1
nullGrob() 可能比 textGrob("") 更好的选项。 - baptiste
2
我向GrobMaster的方向鞠躬。 - IRTFM
我尝试使用'layout.matrix'参数来调用arrangeGrob函数,但失败了,可能是因为我在空白位置上使用了NA而不是0? - IRTFM
我可以尝试在空白位置使用0代替NA。你是如何指定余数的? - viridius
我不确定这有什么关系。我用0代替NA再次尝试,但还是失败了。 - IRTFM
显示剩余9条评论

0

这个版本稍微更加通用一些

interleave <- function(x, y, after = 1){

  nx <- length(x)
  ny <- length(y)

  if((nx %% after) > 0) x <- rep(x, length.out=after * ceiling(nx / after))
  mx <- matrix(x, ncol = after, byrow=TRUE)
  my <- rep(y, length.out = nrow(mx))

  c(t(cbind(mx, my)))
}

library(ggplot2)
library(grid)
library(gridExtra)
x <- replicate(7, ggplot(), simplify=FALSE)
y <- replicate(3, nullGrob(), simplify=FALSE)

marrangeGrob(interleave(x,y,3), ncol=2, nrow=2)

我在for循环之后包含了这个函数(如编辑过的原始帖子所示),但是这并没有产生期望的结果。该函数应该放在其他地方还是需要进行其他编辑? - viridius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接