如何使用grid.arrange安排任意数量的ggplots?

bri*_*ndk 93 r ggplot2

这是在ggplot2 google群组上交叉发布的

我的情况是我正在处理一个输出任意数量的图形的函数(取决于用户提供的输入数据).该函数返回一个n个图的列表,我想将这些图以2 x 2的形式排列.我正在努力解决以下问题:

  1. 如何允许灵活地交给任意(n)个数量的图?
  2. 我怎么能指定我希望它们布局为2 x 2

我目前的策略是grid.arrangegridExtra包中使用.它可能不是最佳的,特别是因为,这是关键,它完全不起作用.这是我评论的示例代码,试验了三个图:

library(ggplot2)
library(gridExtra)

x <- qplot(mpg, disp, data = mtcars)
y <- qplot(hp, wt, data = mtcars)
z <- qplot(qsec, wt, data = mtcars)

# A normal, plain-jane call to grid.arrange is fine for displaying all my plots
grid.arrange(x, y, z)

# But, for my purposes, I need a 2 x 2 layout. So the command below works acceptably.
grid.arrange(x, y, z, nrow = 2, ncol = 2)

# The problem is that the function I'm developing outputs a LIST of an arbitrary
# number plots, and I'd like to be able to plot every plot in the list on a 2 x 2
# laid-out page. I can at least plot a list of plots by constructing a do.call()
# expression, below. (Note: it totally even surprises me that this do.call expression
# DOES work. I'm astounded.)
plot.list <- list(x, y, z)
do.call(grid.arrange, plot.list)

# But now I need 2 x 2 pages. No problem, right? Since do.call() is taking a list of
# arguments, I'll just add my grid.layout arguments to the list. Since grid.arrange is
# supposed to pass layout arguments along to grid.layout anyway, this should work.
args.list <- c(plot.list, "nrow = 2", "ncol = 2")

# Except that the line below is going to fail, producing an "input must be grobs!"
# error
do.call(grid.arrange, args.list)
Run Code Online (Sandbox Code Playgroud)

正如我常常做的那样,我谦卑地蜷缩在角落里,急切地等待着一个比我更聪明的社区的睿智反馈.特别是如果我让它变得比它需要的更难.

JD *_*ong 45

你快到了!问题是do.call希望你的args在一个命名list对象中.您已将它们放在列表中,但作为字符串,而不是命名列表项.

我认为这应该有效:

args.list <- c(plot.list, 2,2)
names(args.list) <- c("x", "y", "z", "nrow", "ncol")
Run Code Online (Sandbox Code Playgroud)

正如Ben和Joshua在评论中指出的那样,我可以在创建列表时指定名称:

args.list <- c(plot.list,list(nrow=2,ncol=2))
Run Code Online (Sandbox Code Playgroud)

要么

args.list <- list(x=x, y=y, z=x, nrow=2, ncol=2)
Run Code Online (Sandbox Code Playgroud)

  • 您可以在列表创建期间命名args:`args.list < - list(x = x,y = y,z = x,nrow = 2,ncol = 2) (2认同)
  • 不完全是.你的长度合适.列表的结构与JD列表的结构不同.使用str()和names().所有列表元素都是未命名的,因此为了使`do.call`成功,需要进行精确的位置匹配. (2认同)
  • @JD Long; 我衷心同意.如果它不能阻止所有错误,那么如果你使用命名参数,你仍会得到更好的错误消息和`traceback()`信息. (2认同)

bap*_*ste 16

试试这个,

require(ggplot2)
require(gridExtra)
plots <- lapply(1:11, function(.x) qplot(1:10,rnorm(10), main=paste("plot",.x)))

params <- list(nrow=2, ncol=2)

n <- with(params, nrow*ncol)
## add one page if division is not complete
pages <- length(plots) %/% n + as.logical(length(plots) %% n)

groups <- split(seq_along(plots), 
  gl(pages, n, length(plots)))

pl <-
  lapply(names(groups), function(g)
         {
           do.call(arrangeGrob, c(plots[groups[[g]]], params, 
                                  list(main=paste("page", g, "of", pages))))
         })

class(pl) <- c("arrangelist", "ggplot", class(pl))
print.arrangelist = function(x, ...) lapply(x, function(.x) {
  if(dev.interactive()) dev.new() else grid.newpage()
   grid.draw(.x)
   }, ...)

## interactive use; open new devices
pl

## non-interactive use, multipage pdf
ggsave("multipage.pdf", pl)
Run Code Online (Sandbox Code Playgroud)

  • `ggsave("multipage.pdf",do.call(marrangeGrob,c(plots,list(nrow = 2,ncol = 2)))) (5认同)
  • 版本> = 0.9 of gridExtra提供marrangeGrob,以便在nrow*ncol <length(plots)时自动完成所有这些操作 (3认同)