R 用“重叠”$&引用;功能

R 用“重叠”$&引用;功能,r,lapply,R,Lapply,假设我有一个data.frames列表 dflist <- list(data.frame(a=1:3), data.frame(b=10:12, a=4:6)) 为什么我不能以同样的方式使用“$”函数 lapply(dflist, `$`, "a") # [[1]] # NULL # # [[2]] # NULL 但这两种方法都有效: lapply(dflist, function(x) x$a) `$`(dflist[[1]], "a") 我意识到在这种情况下,我们可以使用 l

假设我有一个data.frames列表

dflist <- list(data.frame(a=1:3), data.frame(b=10:12, a=4:6))
为什么我不能以同样的方式使用“$”函数

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
lapply(dflist, function(x, z) sys.call())
# [[1]]
# FUN(X[[2L]], ...)

# [[2]]
# FUN(X[[2L]], ...)
库(adegenet)
数据(nancycats)

catpop对于第一个示例,您可以执行以下操作:

lapply(dflist, `$.data.frame`, "a")
对于第二个,使用
slot()
accessor函数

lapply(mylist, "slot", "tab")

我不确定为什么方法分派在第一种情况下不起作用,但是
?lapply
注释部分确实解决了它的基本函数(如
$
)的方法分派问题:

 Note:

 [...]

 For historical reasons, the calls created by ‘lapply’ are
 unevaluated, and code has been written (e.g., ‘bquote’) that
 relies on this.  This means that the recorded call is always of
 the form ‘FUN(X[[i]], ...)’, with ‘i’ replaced by the current
 (integer or double) index.  This is not normally a problem, but it
 can be if ‘FUN’ uses ‘sys.call’ or ‘match.call’ or if it is a
 primitive function that makes use of the call.  This means that it
 is often safer to call primitive functions with a wrapper, so that
 e.g. ‘lapply(ll, function(x) is.numeric(x))’ is required to ensure
 that method dispatch for ‘is.numeric’ occurs correctly.

因此,这个问题似乎更多地与
$
有关,以及它通常如何将不带引号的名称作为第二个参数而不是字符串

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"
)
因此,
z
值被设置为“a”,但是,
$
没有计算第二个参数。因此它返回的是“z”列而不是“a”列。这导致了这组有趣的结果

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
这意味着当调用
$
时,它将
..
分解为字符串
“..”
。这解释了这种行为

dflist<- list(data.frame(a=1:3, "..."=11:13, check.names=F))
lapply(dflist, `$`, "a")
# [[1]]
# [1] 11 12 13

这一个可以用
lappy(dflist,函数(x)“$”(x,“a”))
。问得好。仅供参考,答案可以通过
方法(“$”,dflist[[1]])找到
Well@Frank,并不是我不知道存在
$.data.frame
,我只是惊讶于问题是由方法调度引起的。我想不出还有多少其他情况需要显式调用一种形式的泛型函数。@MrFlick--我同意你的看法。它必须(?)与
lappy()
的奇怪的惰性评估方面有关,但是由于一些(或者,实际上是全部)这种情况发生在C代码级别,我一直无法完全理解它在引擎盖下做什么。@JoshO'Brien我认为这可能更多地是通过
$
而不是Lappy来处理参数。请参见此示例:
f非常感谢您的见解。
slot()
函数是我最后真正想要的,所以我很感谢你提醒我注意这一点。我添加了另一个答案,我认为它更接近于本例中的“为什么”。它实际上更多地是关于泛型
$
实现,而不是
lappy()
从我现在的理解来看。我觉得我可能很密集,但我不太明白这如何解释为什么
lappy(dflist,`$`,“a”)
返回
NULL
。毕竟,
“$”(dflist[[1]],“z”)
返回
31:33
,但显然是等价的调用,
lappy(dflist[1],`$`,“z”)
,返回
NULL
…我缺少什么?啊,好的。嗯,
lappy
有一个额外的级别。它通过
传入参数。…
。因此,如果你截获调用,你会看到传递给函数的第二个参数是“…”.你说得对。这也与lapply如何通过
..
传递参数有关。我也会加进去。哦,伙计,我明白你的意思了。这太吸引人了!看看这个:
df@JoshO'Brien-Heh,是的,这正是我在编辑的内容!:)
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