我需要从包含几百列的data.frame中删除一列.
有了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
Run Code Online (Sandbox Code Playgroud)
显然这仍然有效,但它似乎不是一个非常类似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
Run Code Online (Sandbox Code Playgroud)
但后来我必须构建这样一个笨重的列表.
是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
Run Code Online (Sandbox Code Playgroud)
但真的可能更重要的是内存,如果subset复制整个data.table.
如果您想要永久使用删除列 := NULL
dat[, z := NULL]
Run Code Online (Sandbox Code Playgroud)
如果您要将列作为字符串用于()强制评估作为字符串而不是字符名称.
toDrop <- c('z')
dat[, (toDrop) := NULL]
Run Code Online (Sandbox Code Playgroud)
如果要限制列的可用性.SD,可以传递.SDcols参数
dat[,lapply(.SD, somefunction) , .SDcols = setdiff(names(dat),'z')]
Run Code Online (Sandbox Code Playgroud)
但是,data.table检查j参数并只获取您使用的列.见FAQ 1.12
当您编写X [Y,sum(foo*bar)]时,data.table会自动检查j表达式以查看它使用的列.
并且不会尝试加载所有数据.SD(除非您.SD在通话中j)
subset.data.table 正在处理呼叫并最终进行评估 dat[, c('x','y'), with=FALSE]
使用:= NULL应该基本上是瞬时的,如何永久删除列.
| 归档时间: |
|
| 查看次数: |
322 次 |
| 最近记录: |