vsa*_*dra 13 r data.table
我正在对data.table(优秀包!!!)进行一些聚合,我发现.SD变量对很多东西非常有用.但是,当有许多组时,使用它会显着减慢计算速度.举个例子:
# A moderately big data.table
x = data.table(id=sample(1e4,1e5,replace=T),
code=factor(sample(2,1e5,replace=T)),
z=runif(1e5)
)
setkey(x,id,code)
system.time(x[,list(code2=nrow(.SD[code==2]), total=.N), by=id])
## user system elapsed
## 6.226 0.000 6.242
system.time(x[,list(code2=sum(code==2), total=.N), by=id])
## user system elapsed
## 0.497 0.000 0.498
system.time(x[,list(code2=.SD[code==2,.N], total=.N), by=id])
## user system elapsed
## 6.152 0.000 6.168
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么?我应该避免.SD支持单个列吗?提前致谢.
Mat*_*wle 13
我做错了什么,即我应该避免
.SD支持单个列?
对,就是这样.只有.SD在你真正使用里面的所有数据时才使用.SD.您可能还会发现nrow()对[.data.table内部的调用和子查询调用j也是罪魁祸首:用于Rprof确认.
请参阅FAQ 2.1的最后几句话:
FAQ 2.1我怎样才能避免写一个很长的j表达式?你说我应该使用列名,但我有很多列.
分组时,j表达式可以使用列名作为变量,但是它也可以使用保留符号.SD,该符号引用每个组的Data.table的子集(不包括分组列).所以总结一下你的所有专栏DT[,lapply(.SD,sum),by=grp].它可能看起来很棘手,但编写和快速运行速度很快.请注意,您不必创建匿名函数.查看时序插图和wiki以与其他方法进行比较.该.SD对象在内部有效实现,并且比将参数传递给函数更有效.请不要这样做:DT[,sum(.SD[,"sales",with=FALSE]),by=grp].这有效,但效率低,不够优雅.这是预期的:DT[,sum(sales),by=grp]并且可能快100倍.
另请参阅FAQ 3.1的第一个子弹:
FAQ 3.1我有20列和大量行.为什么一列的表达如此之快?
有几个原因:
- 只有该列被分组,其他19被忽略,因为data.table检查j表达式并意识到它不使用其他列.
当data.table检查j并看到.SD符号时,效率增益就会消失..SD即使您不使用其所有列,也必须为每个组填充整个子集.很难data.table知道.SD你真正使用哪些列(例如j可能包含ifs).但是,如果你无论如何都需要它们,那当然没关系,例如DT[,lapply(.SD,sum),by=...].这是理想的用途.SD.
所以,是的,.SD尽可能避免.直接使用列名来为data.table提供j最佳机会的优化.符号仅仅存在.SD于j非常重要.
这就是为什么.SDcols被引入.因此data.table,.SD如果您只想要一个子集,则可以确定应该包含哪些列.否则,data.table将填充.SD所有列以防万一j需要它们.
| 归档时间: |
|
| 查看次数: |
2621 次 |
| 最近记录: |