6

我需要从包含几百列的 data.frame 中删除一列。

使用 a data.frame,我会很subset方便地做到这一点:

> dat <- data.table( data.frame(x=runif(10),y=rep(letters[1:5],2),z=runif(10)),key='y' )
> subset(dat,select=c(-z))
            x y
 1: 0.1969049 a
 2: 0.7916696 a
 3: 0.9095970 b
 4: 0.3529506 b
 5: 0.4923602 c
 6: 0.5993034 c
 7: 0.1559861 d
 8: 0.9929333 d
 9: 0.3980169 e
10: 0.1921226 e

显然这仍然有效,但它似乎不是一个非常data.table像的成语。我可以手动构建一个我想保留的列名列表,这看起来更像data.table

> dat[,list(x,y)]
            x y
 1: 0.1969049 a
 2: 0.7916696 a
 3: 0.9095970 b
 4: 0.3529506 b
 5: 0.4923602 c
 6: 0.5993034 c
 7: 0.1559861 d
 8: 0.9929333 d
 9: 0.3980169 e
10: 0.1921226 e

但是我必须构建这样一个列表,这很笨重。

subset方便地删除一两列的正确方法,还是会导致性能下降?如果没有,有什么更好的方法?

编辑

基准:

> dat <- data.table( data.frame(x=runif(10^7),y=rep(letters[1:10],10^6),z=runif(10^7)),key='y' )
> microbenchmark( subset(dat,select=c(-z)), dat[,list(x,y)] )
Unit: milliseconds
                         expr       min        lq    median        uq      max
1           dat[, list(x, y)] 102.62826 167.86793 170.72847 199.89789 792.0207
2 subset(dat, select = c(-z))  33.26356  52.55311  53.53934  55.00347 180.8740

但实际上,如果subset复制整个data.table.

4

2 回答 2

9

如果您想永久删除该列,请使用:= NULL

dat[, z := NULL]

如果您将列作为字符串删除,请使用()强制评估作为字符串,而不是作为字符名称。

toDrop <- c('z')

dat[, (toDrop) := NULL]

如果要限制 中的列的可用性.SD,可以传递.SDcols参数

dat[,lapply(.SD, somefunction) , .SDcols = setdiff(names(dat),'z')]

但是,data.table检查j参数并仅获取您以任何方式使用的列。请参阅常见问题解答 1.12

当您编写 X[Y,sum(foo*bar)] 时,data.table 会自动检查 j 表达式以查看它使用了哪些列。

并且不会尝试加载所有数据.SD(除非您.SD在调用范围内j


subset.data.table正在处理呼叫并最终评估dat[, c('x','y'), with=FALSE]

using:= NULL应该基本上是瞬时的,但是 t 确实会永久删除该列。

于 2013-05-10T00:35:21.507 回答
1

我想这就是你要找的。

dat[, !"z"]

这是您编辑的大量数据的基准。

Unit: milliseconds
                         expr       min        lq    median       uq      max neval
  subset(dat, select = c(-z))  53.37435  56.82514  61.81279 100.3458 339.1400   100
            dat[, list(x, y)] 191.46678 354.39905 412.06421 451.3933 678.3981   100
                  dat[, !"z"]  53.49184  57.31756  62.15506 112.7063 398.0107   100
于 2013-05-10T00:43:46.333 回答