lapply with" $"功能

时间:2015-05-08 19:32:54

标签: r lapply

我们说我有一个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

2 个答案:

答案 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