Rdata.table.SD意外行为
我试图计算数据表的一些基本统计数据,但我遇到了这种(对我而言)意外的行为。如果我使用“显式”索引使用所有内容进行计算,则一切都按预期工作,如下例所示:
library(data.table)
n <- 100; reps <- 6; n1 <- 2
df <- as.data.frame(cbind(matrix(seq_len(n*n1), ncol=n1),
matrix(sample(0:1000, n*reps, replace=TRUE), ncol=reps)))
dt <- data.table(df)
dtmean <- dt[, lapply(.SD[,c(seq(2,5))], mean, na.rm=TRUE), by=c("V1")]
但如果我使用
a=2
b=5
dtmean <- dt[, lapply(.SD[,c(seq(a,b))], mean, na.rm=TRUE), by=c("V1")]
结果不是我所期望的(前几行)
这是故意的 data.table 应该如何工作吗?
所以 n=10 的第一部分代码给出
V1 V3 V4 V5 V6
1: 1 504 399 430 564
2: 2 547 294 274 700
3: 3 555 305 781 326
4: 4 144 840 983 221
5: 5 894 659 169 38
6: 6 788 289 598 433
7: 7 810 378 86 22
8: 8 848 212 701 565
9: 9 412 707 890 160
10: 10 82 580 927 607
而第二
V1 V1 V2 V3 V4
1: 1 2 3 4 5
2: 2 2 3 4 5
3: 3 2 3 4 5
4: 4 2 3 4 5
5: 5 2 3 4 5
6: 6 2 3 4 5
7: 7 2 3 4 5
8: 8 2 3 4 5
9: 9 2 3 4 5
10: 10 2 3 4 5
他们不应该给我同样的结果吗?这里的函数 mean 不计算任何东西,因为 V1 有所有不同的值,问题是关于索引的选择,我不明白为什么它们以不同的方式工作。
回答
您应该使用.SDcols来控制.SD在这种情况下包含的内容:
dtmean <- dt[, lapply(.SD, mean, na.rm=TRUE), by="V1", .SDcols=seq(a,b)]
要做到你的风格,你应该with=FALSE在内部.SD调用中使用:
dtmean <- dt[, lapply(.SD[, seq(a,b), with=FALSE], mean, na.rm=TRUE), by=c("V1")]
.SD本身是 a data.table,因此[具有相同的语义,即问题与之间的差异相同
dt[ , seq(a,b)]
和
dt[ , seq(a,b), with=FALSE]
附录需要注意的是.SDcols,也可以用来确定a,b内嵌在某些情况下,例如,如果a:b仅仅是表的数值列,我们可以使用:
dt[ , lapply(.SD, mean, na.rm=TRUE), by=V1, .SDcols=is.numeric]
或者,如果a:b他们的名字中有一个模式,例如:
dt[ , lapply(.SD, mean, na.rm=TRUE), by=V1, .SDcols=patterns("ends_with_x$")]