我有一个数据框列表(这里以2为例)。
df1 <- read.table(text= "var,X2x,X4x,X6x
101337,4.631833,4.4547,11.097333
345754,3.727433,10.8560,10.536600" ,header=TRUE, sep=",")
df2 <- read.table(text= "var,X2x,X4x,X6x
101337,5.631833,10.4547,11.097333
345754,5.727433,12.8560,10.536600" ,header=TRUE, sep=",")
dflist <- list(df1=df1, df2=df2)
我想使用lapply来浏览每个data.frame并使用apply进行简单的比较(即检查第二列的值是否大于第三列),给定结果,添加一个新的带有标记的列(在示例中,然后新列称为“因子”。)
我差不多了,但我的脚本输出错误,返回了一个向量列表,而不是带有添加列的data.frames列表。
这是代码:
dfL <- lapply(dflist,function(dfx) {
apply(dfx,1, function(df) { if(df[3] < (df[4] )) {
dfx$factor<-"nonNA"} else {dfx$factor<-"NA"}
}
)
}
)
请你解释一下我做错了什么?
答案 0 :(得分:4)
您的方法存在一些问题。首先,您要从最里面的应用修改dfx
,但是您使用简单的<-
运算符代替<<-
运算符。前一个运算符不会影响函数范围之外的事物。我也不主张使用<<-
(请参阅此处的替代方案)。
您遇到的另一个问题是,您没有指定要在dfx
内更新apply
的哪一行,所以即使您有<<-
每一行都会更新,而您无论最后的测试比较是什么,最终的结果都是最终的。
最后,您要在apply
中返回dfx
的结果,而不是修改后的lapply
。
在这里,我们将transform
函数应用于每个数据框,以根据数据框中第3和第4列的值(此处按名称引用)添加factor
列。请注意我是如何使用ifelse
来避免内部apply
:
lapply(dflist, transform, factor=ifelse(X4x < X6x, "nonNA", "NA"))
# $df1
# var X2x X4x X6x factor
# 1 101337 4.631833 4.4547 11.09733 nonNA
# 2 345754 3.727433 10.8560 10.53660 NA
#
# $df2
# var X2x X4x X6x factor
# 1 101337 5.631833 10.4547 11.09733 nonNA
# 2 345754 5.727433 12.8560 10.53660 NA
这是一个不必要的变化,它更接近你想要做的事情,比较/对比,希望你能更清楚地看到为什么你的工作不起作用:
lapply(dflist,
function(dfx) {
dfx$factor <- ""
lapply(1:nrow(dfx),
function(row.id) {
dfx[row.id, "factor"] <<-
if(dfx[row.id, 3] < dfx[row.id, 4]) "nonNA" else "NA"
} )
dfx
} )
注意我在内循环中lapply
而不是apply
的方式,以便我可以跟踪行号。同样,我不推荐这种方法,但它是出于解释目的。
答案 1 :(得分:2)
您可以尝试这样的事情。对于矢量化操作,您不需要apply
。
lapply(dflist, function(x){
x$grp <- "not smaller"
x$grp[x[ , 3] < x[ , 4]] <- "smaller"
x
})
# $df1
# var X2x X4x X6x grp
# 1 101337 4.631833 4.4547 11.09733 smaller
# 2 345754 3.727433 10.8560 10.53660 not smaller
#
# $df2
# var X2x X4x X6x grp
# 1 101337 5.631833 10.4547 11.09733 smaller
# 2 345754 5.727433 12.8560 10.53660 not smaller