Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R将ggplot对象指定给循环中的列表_R_Loops_Ggplot2_Cowplot - Fatal编程技术网

R将ggplot对象指定给循环中的列表

R将ggplot对象指定给循环中的列表,r,loops,ggplot2,cowplot,R,Loops,Ggplot2,Cowplot,我正在使用for循环将ggplot分配给列表,然后将其传递给plot\u grid()(包cowplot)绘图网格将多个GGPlot并排放置在一个图形中。手动操作效果很好,但当我将用于循环时,生成的最后一个绘图将在图形的每个子帧中重复(如下所示)。换句话说,所有子帧显示相同的ggplot 以下是一个玩具示例: require(cowplot) dfrm <- data.frame(A=1:10, B=10:1) v <- c("A","B") dfmsize <- nrow

我正在使用
for循环
将ggplot分配给
列表
,然后将其传递给
plot\u grid()
(包
cowplot
)<代码>绘图网格将多个GGPlot并排放置在一个图形中。手动操作效果很好,但当我将
用于循环
时,生成的最后一个绘图将在图形的每个子帧中重复(如下所示)。换句话说,所有子帧显示相同的ggplot

以下是一个玩具示例:

require(cowplot)

dfrm <- data.frame(A=1:10, B=10:1)

v <- c("A","B")
dfmsize <- nrow(dfrm)
myplots <- vector("list",2)

count = 1
for(i in v){
    myplots[[count]] <- ggplot(dfrm, aes(x=1:dfmsize, y=dfrm[,i])) + geom_point() + labs(y=i)
    count = count +1
}
plot_grid(plotlist=myplots)
但我得到了同样的结果


我认为问题在于循环赋值,而不是
plot\u grid()
,但我看不出我做错了什么。

我认为
ggplot
会因为在
dfrm
中查找
x
y
变量而变得混乱,即使您实际上正在动态定义它们。如果您稍微更改
for
循环,以构建一个新的子
data.frame
作为第一行,它就可以正常工作

myplots <- list()
count = 1

for(i in v){
    df <- data.frame(x = 1:dfmsize, y = dfrm[,i])
    myplots[[count]] <- ggplot(df, aes(x=x, y=y)) + geom_point() + labs(y=i)
    count = count + 1
}
plot_grid(plotlist=myplots)

myplots对于ggplot2的延迟计算和[this answer]中的for循环,有一个很好的解释(

对于这种情况,我通常切换到
aes\u string
aes\u
,这样我就可以在ggplot2中将变量用作字符串

我发现
lappy
循环比
for
循环更容易,因为可以避免初始化列表和使用计数器

首先,我将x变量添加到数据集中

dfrm$index = 1:nrow(dfrm)
现在,
lappy
循环,循环通过
v
中的列

myplots = lapply(v, function(x) {
    ggplot(dfrm, aes_string(x = "index", y = x)) + 
        geom_point() +
        labs(y = x)
})

plot_grid(plotlist = myplots)

我认为这里的问题是,对
aes
方法的非标准评估会延迟评估
I
,直到实际绘制出绘图。绘制时,
I
是最后一个值(在玩具示例“B”中)因此,所有绘图的
y
美学映射引用最后一个值。同时,
labs
调用使用标准评估,因此标签正确引用循环中
i
的每个迭代

只需使用映射函数的标准求值版本,
aes\u q
,即可解决此问题:

require(cowplot)

dfrm <- data.frame(A=1:10, B=10:1)

v <- c("A","B")
dfmsize <- nrow(dfrm)
myplots <- vector("list",2)

count = 1
for(i in v){
    myplots[[count]] <- ggplot(dfrm, aes_q(x=1:dfmsize, y=dfrm[,i])) + geom_point() + labs(y=i)
    count = count +1
}
plot_grid(plotlist=myplots)
require(整流罩图)

dfrm到目前为止,答案非常接近,但在我看来并不令人满意。问题是以下问题-在您的
for
循环之后:

myplots[[1]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, i]
myplots[[1]]$plot_env
#<environment: R_GlobalEnv>

myplots[[2]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, i]
myplots[[2]]$plot_env
#<environment: R_GlobalEnv>

i
#[1] "B"
myplots[[1]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, col]
myplots[[1]]$plot_env
#<environment: 0x000000000bc27b58>

myplots[[2]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, col]
myplots[[2]]$plot_env
#<environment: 0x000000000af2ef40>

eval(quote(dfrm[, col]), env = myplots[[1]]$plot_env)
#[1]  1  2  3  4  5  6  7  8  9 10
eval(quote(dfrm[, col]), env = myplots[[2]]$plot_env)
#[1] 10  9  8  7  6  5  4  3  2  1
之所以这样做,是因为环境对于
lappy
循环中的每个值都是不同的:

myplots[[1]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, i]
myplots[[1]]$plot_env
#<environment: R_GlobalEnv>

myplots[[2]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, i]
myplots[[2]]$plot_env
#<environment: R_GlobalEnv>

i
#[1] "B"
myplots[[1]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, col]
myplots[[1]]$plot_env
#<environment: 0x000000000bc27b58>

myplots[[2]]$mapping
#* x -> 1:dfmsize
#* y -> dfrm[, col]
myplots[[2]]$plot_env
#<environment: 0x000000000af2ef40>

eval(quote(dfrm[, col]), env = myplots[[1]]$plot_env)
#[1]  1  2  3  4  5  6  7  8  9 10
eval(quote(dfrm[, col]), env = myplots[[2]]$plot_env)
#[1] 10  9  8  7  6  5  4  3  2  1

详细介绍了ggplot2惰性评估的一些本质。我喜欢你明确提到NSE。在将绘图分配给列表之前,还可以通过在循环中实际打印绘图来验证NSE,这实际上给出了正确的输出(不同于在循环运行后打印)。我将eddi标记为最佳答案,因为通过映射,然后显示循环的每个迭代,
plot_env
,可以清楚地看到发生了什么。@jrandall:我没有意识到aes执行非标准评估,正如您所提到的,这就是为什么最好使用
aes_q.对其他人提到的
lapply`作为f的替代或循环。@eddi我试图说服
ggplot
for
循环期间,当我最终检查存储在绘图列表中的所有绘图时,遵守绘图生成时的变量值。您对此有何建议?
ls(myplots[[1]]$plot_env)
#[1] "col"