使用lapply的情节列表

时间:2014-03-07 13:50:37

标签: r ggplot2 lapply

我最近一直在使用lapply和sapply作为我的首选功能。到目前为止这么好,但为什么下面的代码不起作用让我感到困惑。

df<-as.data.frame(matrix(rnorm(50),ncol=5))
names(df)<-c("x1","x2","x3","x4","x5")
df1<-seq_len(10)

ll<-lapply(seq(1,5), function(i) qplot(df1,df[,i]))

我收到错误:

Error in `[.data.frame`(df, , i) : undefined columns selected

好吧,显然我在可重现的代码中犯了一个很不幸的错误。它现在有效,但ll列表中的所有图都是相同的图。当我运行时:

do.call(grid.arrange,ll)

我得到以下图片:

Grid

所有的情节都是一样的!这也是我通过数据运行时获得的输出。

3 个答案:

答案 0 :(得分:6)

懒惰评估存在问题,或者类似的问题。您需要执行以下操作:

ll<-lapply(
  seq(1,5), 
  function(i) qplot(data=data.frame(y=df[, i]), df1, y)
)

这将强制为每个图更新y值。

在其他 SO Post 中进行更多讨论。

答案 1 :(得分:5)

您遇到的问题与延迟评估有关。这意味着ll中的函数只有在您调用grid.arrange时才会真正进行评估。那时,每个函数都会尝试找到i,此时的值为5,因为这是i末尾lapply的最后一个值循环。因此,从df提取的数据始终是第五列,因此您的绘图都是相同的。

为了防止这种情况,您需要在创建函数时强制进行数据提取,例如使用@ BrodieG的方法。在那里,创建了一个新的data.frame,强制从df获取数据。或者,您可以使用force强制评估i

另请参阅有关延迟评估的更多示例和说明:


要在同一data.frame中创建多列的绘图,我会使用facet_wrap。要使用facet_wrap,您需要使用melt包中的reshape2重新排序数据:

library(ggplot2)
library(reshape2)
df$xvalues = 1:10
df_melt = melt(df, id.vars = 'xvalues')
ggplot(df_melt, aes(x = xvalues, y = value)) + 
    geom_point() + facet_wrap(~ variable)

enter image description here

答案 2 :(得分:3)

你告诉它要执行10列,你只有5个。这样可以:

ll<-lapply(seq(1,5), function(i) qplot(df1,df[,i]))