lapply函数中的data.table找不到对象

8
假设我有以下 R 代码:
library(data.table)
L <- list(a=data.table(x=c(1,2,3),y=c(10,20,30)),
          b=data.table(x=c(4,5,6),y=c(40,50,60)),
          c=data.table(x=c(7,8,9),y=c(70,80,90)))


columnName <- "x"         
r <- lapply(L,"[",i=get(columnName) %in% c(1,4))

f <- function(L1) {
     columnName1 <- "x"
     r1 <- lapply(L1,"[",i=get(columnName1) %in% c(1,4))
     return(r1)
}

r1 <- f(L)

我的问题是:为什么在函数内部底部对r1的赋值失败,出现了“Error in get(columnName1) : object 'columnName1' not found”错误提示?
在函数上方对r的赋值正常。同样地,如果我在函数内部通过<<-进行全局赋值columnName1,那么我就创建了一个我不真正需要的全局变量。我该如何重新编写代码,使得data.table能够在其范围内找到columnName1?我对作用域的理解是否有误?我本以为如果在“[”函数中找不到columnName1,它会向上查找一个环境并在那里找到它?但它必须在全局环境中查找,而不是在父环境中查找?
2个回答

1

我猜测你想从 data.table 中返回什么。如果你想返回列 x 等于1和4的行,通常最好先使用列表中的单个值使其有效,然后再使用lapply

library(data.table)
columnName1 <- "x"
L$a[get(columnName1) %in% c(1,4)]

遍历列表。
lapply(L, function(x) x[get(columnName1) %in% c(1,4)])

如果您需要一个可以指定列名和行号的函数

f <- function(list, col, row) {lapply(list, function(x, lcol, lrow) x[get(lcol) %in% lrow], lcol=col, lrow=row)}
f(L, "x", c(1,4))

0

lapply 的语法糖可能会使事情变得更加复杂,因为表达式将被视为参数,这使得很难知道表达式被评估的环境。此外,当与 data.table() 一起使用时,get() 函数可能已经被修改,因为其签名与正常用例不同。在这里的一个解决方法是创建自己的匿名函数,确保 get 将在 [.data.table 调用中被评估。

f <- function(L1) {
     columnName1 <- "x"
     r1 <- lapply(L1, function(x) x[i=get(columnName1) %in% c(1,4)])
     r1
}

r1 <- f(L)

r1
#$a
#   x  y
#1: 1 10

#$b
#   x  y
#1: 4 40

#$c
#Empty data.table (0 rows) of 2 cols: x,y

仍然不确定是什么原因导致失败,也许一些 data.table 专家可以在这里澄清。


使用匿名函数起作用了。我想我是在使用“[”与lapply和data.table相结合时有点过度尝试了。 - user5577796
@user5577796 这可能与在使用可选参数时 lapply 的环境有关。如果您的原始函数 f 使用全局环境中存在的 columnName 而不是 columnName1,它就可以工作了。 - manotheshark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接