【问题标题】:R data.table .SD unexpected behaviourR data.table .SD 意外行为
【发布时间】:2021-05-08 11:44:15
【问题描述】:

我试图计算数据表的一些基本统计数据,但我遇到了这个(对我而言)意想不到的行为。 如果我使用“显式”索引计算所有内容,则所有内容都按预期工作,如下例所示:

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 具有所有不同的值,问题是关于索引的选择,我不明白为什么它们以不同的方式工作。

【问题讨论】:

  • 你到底拿了什么mean 的?从您的输出看来,您只是在选择列。 dt[, c(1, 3:6)]
  • 请查看已编辑的问题
  • dt[, lapply(.SD[,seq(a,b),with=FALSE], mean, na.rm=TRUE), by=c("V1")] 工作。我猜测data.table 认为a 和b 应该代表.SD 环境中的变量,因此防止这种行为在.SD 中是钥匙。我不知道seq(2,5) 有效而seq(a,b) 无效是否真的是故意的,但with= 肯定会回避这里的问题。
  • 顺便说一句,dt[, lapply(.SD[,a:b], mean, na.rm=TRUE), by=c("V1")] 也有效(a:b,没有with=)。我认为这绝对是data.table 中 NSE 的一个极端案例。我不知道这是否是一个错误,我希望data.table 开发人员之一可以通知讨论。 (如果没有,最好将其作为issue 提出。)

标签: r data.table


【解决方案1】:

在这种情况下,您应该使用.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,所以[ 具有相同的语义,即issue 与两者的区别相同

dt[ , seq(a,b)]

和

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

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

【讨论】:

    猜你喜欢
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多