【发布时间】:2013-05-24 06:11:04
【问题描述】:
与数据帧相比,使用data.table 进行类似tapply 的操作在速度方面的提升给我留下了深刻的印象。
例如:
df = data.frame(class = round(runif(1e6,1,1000)), x=rnorm(1e6))
DT = data.table(df)
# takes ages if somefun is complex
res1 = tapply(df$x, df$class, somefun)
# takes much faster
setkey(DT, class)
res2 = DT[,somefun(x),by=class]
但是,在类似apply 的操作(即,需要将函数应用于每一行的情况)中,我并没有设法让它明显快于数据帧。
df = data.frame(x1 = rnorm(1e6), x2=rnorm(1e6))
DT = data.table(df)
# takes ages if somefun is complex
res1 = apply(df, 1, somefun)
# not much improvement, if at all
DT[,rowid:=.I] # or: DT$rowid = 1:nrow(DT)
setkey(DT, rowid)
res2 = DT[,somefun1(x1,x2),by=rowid]
这真的只是意料之中还是有一些技巧?
【问题讨论】:
-
apply将在内部强制转换为矩阵(复制,列必须全部相同)。data.table有很多开销——你真的想矢量化一些乐趣 -
我希望你能在矢量化 somefun 时玩得开心。
-
不幸的是,我只能想象通过迭代行号 rowid 然后在 mclapply 中为 df[rowid,] 运行并行计算来“矢量化”它。这可以完成这项工作,但非常耗费资源。
-
这是不可重现的,但即使显示了什么,我们也可以看到,在帖子的后半部分,这两个代码没有可比性——在
res1的计算中,一个参数被传递给 @ 987654329@ 和res2的情况下传递了两个参数。 -
是的,确实 somefun 在这两种情况下都必须写得有点不同,但我的印象是其他人理解我的意思。在上一个示例中将 somefun 更改为 somefun1 以避免混淆。是的,mnel 通过矢量化为我打开了全新的世界,正如我现在所意识到的 - 非常感谢!
标签: r data.table