为什么我不能在data.table中使用.I删除当前观察?

Fin*_*ino 2 r data.table

最近我看到了一个类似这样的问题(找不到链接)

我想在data.frame上添加一列,用于计算不同列的方差,同时删除当前观察.

dt = data.table(
  id = c(1:13),
  v = c(9,5,8,1,25,14,7,87,98,63,32,12,15)
)
Run Code Online (Sandbox Code Playgroud)

所以,for()循环:

res = NULL
for(i in 1:13){
  res[i] = var(dt[-i,v])
}
Run Code Online (Sandbox Code Playgroud)

我尝试在data.table中使用负索引来执行此操作.I,但令我惊讶的是,以下所有工作都没有:

#1
dt[,var := var(dt[,v][-.I])]

#2
dt[,var := var(dt$v[-.I])]

#3 
fun = function(x){
  v = c(9,5,8,1,25,14,7,87,98,63,32,12,15)
  var(v[-x])
}
dt[,var := fun(.I)]

#4
fun = function(x){
  var(dt[-x,v])
}
dt[,var := fun(.I)]
Run Code Online (Sandbox Code Playgroud)

所有这些都给出了相同的输出:

    id  v var
 1:  1  9  NA
 2:  2  5  NA
 3:  3  8  NA
 4:  4  1  NA
 5:  5 25  NA
 6:  6 14  NA
 7:  7  7  NA
 8:  8 87  NA
 9:  9 98  NA
10: 10 63  NA
11: 11 32  NA
12: 12 12  NA
13: 13 15  NA
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我认为这是.I传递给函数的一个问题,但是一个虚拟的例子:

fun = function(x,c){
  x*c
}
dt[,dummy := fun(.I,2)]

    id  v var
 1:  1  9   2
 2:  2  5   4
 3:  3  8   6
 4:  4  1   8
 5:  5 25  10
 6:  6 14  12
 7:  7  7  14
 8:  8 87  16
 9:  9 98  18
10: 10 63  20
11: 11 32  22
12: 12 12  24
13: 13 15  26
Run Code Online (Sandbox Code Playgroud)

工作良好.

为什么我不能.I在这个特定情况下使用?

Hen*_*rik 7

你可以使用.BY:

a list包含每个项目的长度为1的向量by

dt[ , var_v := dt[id != .BY$id,  var(v)], by = id]
Run Code Online (Sandbox Code Playgroud)

每行计算一次方差(by = id).在每次计算中,使用id != .BY$id"内部" 排除当前行i.

all.equal(dt$var_v, res)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

为什么你的代码不起作用?因为...

.I是一个等于的整数向量seq_len(nrow(x)),

...你-.I不仅会删除当前的观察结果,还会从"v"中删除所有行.

一个小例子,从你的尝试开始(只是没有任务:=),并逐步简化:

# your attempt
dt[ , var(dt[, v][-.I])]
# [1] NA

# without the `var`, indexing only
dt[ , dt[ , v][-.I]]
# numeric(0)
# an empty vector

# same indexing written in a simpler way
dt[ , v[-.I]]
# numeric(0)

# even more simplified, with a vector of values
# and its corresponding indexes (equivalent to .I)
v <- as.numeric(11:14)
i <- 1:4
v[i]
# [1] 11 12 13 14

x[-i]
# numeric(0)
Run Code Online (Sandbox Code Playgroud)

  • @Fino我添加了一些解释.如果有意义,请告诉我.干杯. (3认同)
  • 没有我的外部功能很好用.当你知道它们存在并且知道如何使用它们时,`data.table`中的点大写命令会派上用场.谢谢! (2认同)