我最近一直在使用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)
我得到以下图片:
所有的情节都是一样的!这也是我通过数据运行时获得的输出。
答案 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)
答案 2 :(得分:3)
你告诉它要执行10列,你只有5个。这样可以:
ll<-lapply(seq(1,5), function(i) qplot(df1,df[,i]))