我正在尝试在for循环中使用 ggplot2 在网格上绘制多个图,然后是grid.arrange
。但此后所有情节都是相同的。
library(ggplot2)
library(grid)
test = data.frame(matrix(rnorm(320), ncol=16 ))
names(test) = sapply(1:16, function(x) paste0("var_",as.character(x)))
plotlist = list()
for (i in 1:(dim(test)[2]-1)){
plotlist[[i]] = ggplot(test) +
geom_point(aes(get(x=names(test)[dim(test)[2]]), y=get(names(test)[i])))
}
pdf("output.pdf")
do.call(grid.arrange, list(grobs=plotlist, nrow=3))
dev.off(4)
运行此代码时,似乎get()
调用仅在grid.arrange
调用时进行评估,因此图中的所有y向量均与“ var_15”相同。有没有一种方法可以立即进行评估,以便获得15个不同的地块?
谢谢!
答案 0 :(得分:1)
尝试一下:
library(ggplot2)
library(grid)
library(gridExtra)
set.seed(1234)
test = data.frame(matrix(rnorm(320), ncol=16 ))
names(test) = sapply(1:16, function(x) paste0("var_",as.character(x)))
plotlist = list()
for (i in 1:(dim(test)[2]-1)) {
# Define here the dataset for the i-th plot
df <- data.frame(x=test$var_16, y=test[, i])
plotlist[[i]] = ggplot(data=df, aes(x=x, y=y)) + geom_point()
}
grid.arrange(grobs=plotlist, nrow=3)
答案 1 :(得分:1)
有两种使用purrr::map
函数而不是for循环的方法。我发现当我尝试使用循环时,我对所发生的事情不太了解,而且由于apply
和map
系列之类的函数非常适合R的向量运算范例,我通常改用映射。
第一个示例使用cowplot::plot_grid
,它可以获取图表列表并进行排列。第二种使用更新的patchwork
包,它使您可以将图添加在一起(如直译为plot1 + plot2
一样)并添加布局。要进行所有这些添加,我将purrr::reduce
与+
一起使用,作为应用于所有图的函数。
library(tidyverse)
set.seed(722)
test = data.frame(matrix(rnorm(320), ncol=16 ))
names(test) = sapply(1:16, function(x) paste0("var_",as.character(x)))
# extract all but last column
xvars <- test[, -ncol(test)]
通过使用purrr::imap
,我可以映射所有列并应用带有2个参数的函数:列本身及其名称。这样,我可以设置一个x轴标签来指定列名。我也可以轻松访问数据列,而不必使用get
或任何tidyeval技巧(尽管对于复杂的事情,tidyeval解决方案可能会更好)。
plots <- imap(xvars, function(variable, var_name) {
df <- data_frame(x = variable, y = test[, ncol(test)])
ggplot(df, aes(x = x, y = y)) +
geom_point() +
xlab(var_name)
})
cowplot::plot_grid(plotlist = plots, nrow = 3)
library(patchwork)
# same as plots[[1]] + plots[[2]] + plots[[3]] + ...
reduce(plots, `+`) + plot_layout(nrow = 3)
由reprex package(v0.2.0)于2018-07-22创建。