R数据表.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)]

要按照自己的风格进行操作,您应该在内部.SD调用中使用with=FALSE

dtmean <- dt[, lapply(.SD[, seq(a,b), with=FALSE], mean, na.rm=TRUE), by=c("V1")]

.SD本身就是data.table,因此[具有相同的语义,即问题与之间的差异相同

dt[ , seq(a,b)]

dt[ , seq(a,b), with=FALSE]

注意,在某些情况下,.SDcols也可用于确定ab内联,例如,如果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$")]

最新更新