我们说我有一个data.frames列表
dflist <- list(data.frame(a=1:3), data.frame(b=10:12, a=4:6))
如果我想从列表中的每个项目中提取第一列,我可以
lapply(dflist, `[[`, 1)
# [[1]]
# [1] 1 2 3
#
# [[2]]
# [1] 10 11 12
为什么我不能使用&#34; $&#34;以同样的方式运作
lapply(dflist, `$`, "a")
# [[1]]
# NULL
#
# [[2]]
# NULL
但这些都有效:
lapply(dflist, function(x) x$a)
`$`(dflist[[1]], "a")
我意识到在这种情况下可以使用
lapply(dflist, `[[`, "a")
但我正在处理一个似乎不允许通过[[
进行索引的S4对象。例如
library(adegenet)
data(nancycats)
catpop <- genind2genpop(nancycats)
mylist <- list(catpop, catpop)
#works
catpop[[1]]$tab
#doesn't work
lapply(mylist, "$", "tab")
# Error in slot(x, name) :
# no slot of name "..." for this object of class "genpop"
#doesn't work
lapply(mylist, "[[", "tab")
# Error in FUN(X[[1L]], ...) : this S4 class is not subsettable
答案 0 :(得分:28)
对于第一个例子,你可以这样做:
lapply(dflist, `$.data.frame`, "a")
对于第二个,请使用slot()
访问者功能
lapply(mylist, "slot", "tab")
我不确定为什么方法调度在第一种情况下不起作用,但Note
的{{1}}部分确实解决了这个问题它的borked方法调度用于原始函数,如?lapply
:
$
答案 1 :(得分:13)
所以看起来这个问题更多地与$
有关,以及它通常如何将未加引号的名称作为第二个参数而不是字符串。看看这个例子
dflist <- list(
data.frame(a=1:3, z=31:33),
data.frame(b=10:12, a=4:6, z=31:33)
)
lapply(dflist,
function(x, z) {
print(paste("z:",z));
`$`(x,z)
},
z="a"
)
我们看到了结果
[1] "z: a"
[1] "z: a"
[[1]]
[1] 31 32 33
[[2]]
[1] 31 32 33
因此z
值设置为&#34; a&#34;,但$
不评估第二个参数。所以它回归了&#34; z&#34;列而不是&#34; a&#34;柱。这导致了这组有趣的结果
a<-"z"; `$`(dflist[[1]], a)
# [1] 1 2 3
a<-"z"; `$`(dflist[[1]], "z")
# [1] 31 32 33
a<-"z"; `$.data.frame`(dflist[[1]], a)
# [1] 31 32 33
a<-"z"; `$.data.frame`(dflist[[1]], "z")
# [1] 31 32 33
当我们直接调用$.data.frame
时,我们绕过了在调度之前在原语中发生的标准deparsing(发生在源中的here附近)。
lapply
添加的附带内容是它通过...
机制将参数传递给函数。例如
lapply(dflist, function(x, z) sys.call())
# [[1]]
# FUN(X[[2L]], ...)
# [[2]]
# FUN(X[[2L]], ...)
这意味着当调用$
时,它会将...
转换为字符串"..."
。这解释了这种行为
dflist<- list(data.frame(a=1:3, "..."=11:13, check.names=F))
lapply(dflist, `$`, "a")
# [[1]]
# [1] 11 12 13
当您尝试自己使用...
f<-function(x,...) `$`(x, ...);
f(dflist[[1]], "a");
# [1] 11 12 13
`$`(dflist[[1]], "a")
# [1] 1 2 3