我有一个带有逻辑列的data.table
。为什么逻辑列的名称不能直接用于i
参数?请参见以下示例。
dt <- data.table(x = c(T, T, F, T), y = 1:4)
# Works
dt[dt$x]
dt[!dt$x]
# Works
dt[x == T]
dt[x == F]
# Does not work
dt[x]
dt[!x]
我有一个带有逻辑列的data.table
。为什么逻辑列的名称不能直接用于i
参数?请参见以下示例。
dt <- data.table(x = c(T, T, F, T), y = 1:4)
# Works
dt[dt$x]
dt[!dt$x]
# Works
dt[x == T]
dt[x == F]
# Does not work
dt[x]
dt[!x]
来自 ?data.table
高级: 当
i
是一个单一的变量名称时,它不被视为列名称的表达式,而是在调用作用域中进行求值。
所以dt[x]
将尝试在调用作用域中(在本例中为全局环境)评估x
您可以通过使用(
或{
或force
解决此问题
dt[(x)]
dt[{x}]
dt[force(x)]
x
在全局环境中未定义。如果你尝试这样做,
> with(dt, dt[x])
x y
1: TRUE 1
2: TRUE 2
3: TRUE 4
> attach(dt)
> dt[!x]
x y
1: FALSE 3
编辑:
根据文档,j
参数接受列名,事实上:
> dt[x]
Error in eval(expr, envir, enclos) : object 'x' not found
> dt[j = x]
[1] TRUE TRUE FALSE TRUE
那么,i
参数需要采用数字或逻辑表达式(就像 x 本身应该是的那样)。但是,如果没有这个东西,它(data.table)似乎无法将 x
视为逻辑值:
> dt[i = x]
Error in eval(expr, envir, enclos) : object 'x' not found
> dt[i = as.logical(x)]
x y
1: TRUE 1
2: TRUE 2
3: TRUE 4
x
在全局环境中未定义,但 dt[x == T]
可以工作。 - djhurioError in eval(expr, envir, enclos) : object 'x' not found
表明了这一点。所以,你可能发现了一个潜在的 bug。 - Michele[.data.table
的文档中,无论是 i
还是 j
部分都说“表达式在 data.table 的框架内进行评估(即它将列名视为变量)”。然而,在 i
参数中似乎需要一个显式的表达式,如 ==
或 as.logical
。 - Michelesetkey(dt, x)
dt[J(TRUE)]
dt[J(FALSE)]
force
函数使用。在这种情况下,force
如何工作?它如何改变环境/作用域? - Nishanthforce
基本上阻止它被解释为单个变量(这是在[.data.table
调用中通过一些计算完成的)。然后,force
强制评估x
,这将在data.table范围内返回x
。 - mnelforce
之所以起作用,是因为它使i
不再是单一的名称。dt[identity(x)]
也会出现同样的情况,或者只需使用dt[(x)]
最简单。我也有点喜欢在:=
的LHS上使用(x)
,而不是with=FALSE
,所以(x)
开始成为惯用的data.table
(虽然这更多是偶然而非设计)。 - Matt Dowle