我正在尝试获取具有多个索引的非常大的记录集,计算由索引子集确定的组的聚合统计数据,然后将其插入表中的每一行。这里的问题是这些表非常大——每个表超过 1000 万行。
复制数据的代码如下。
基本思想是有一组索引,比如 ix1, ix2, ix3, ..., ixK。一般来说,我只选择其中的几个,比如 ix1 和 ix2。然后,我为名为val
. 为简单起见,我将重点放在总和上。
我尝试了以下方法
通过稀疏矩阵:将值转换为坐标列表,即 (ix1, ix2, val),然后创建一个 sparseMatrix - 这很好地总结了所有内容,然后我只需从稀疏矩阵表示转换回坐标列表。速度:很好,但它做的超出了必要的范围,它没有推广到更高的维度(例如 ix1、ix2、ix3)或更通用的函数而不是总和。
使用
lapply
andsplit
:通过为所有 (ix1, ix2, ...) n 元组创建一个唯一的新索引,然后我可以使用拆分和应用。这里的坏处是唯一索引被转换split
为一个因子,这种转换非常耗时。试试system({zz <- as.factor(1:10^7)})
。我现在正在尝试
data.table
通过类似的命令sumDT <- DT[,sum(val),by = c("ix1","ix2")]
。但是,除了通过类似的方法之外,我还没有看到如何sumDT
与合并DT
DT2 <- merge(DT, sumDT, by = c("ix1","ix2"))
这个 data.table 连接有没有比merge
我描述的操作更快的方法?
【我也试过bigsplit
从bigtabulate
包里,还有一些其他的方法。任何转换为因子的东西都差不多 - 据我所知,转换过程非常缓慢。]
生成数据的代码。自然,最好尝试更小N
的方法来查看是否有效,但并非所有方法都能很好地扩展到N
>> 1000。
N <- 10^7
set.seed(2011)
ix1 <- 1 + floor(rexp(N, 0.01))
ix2 <- 1 + floor(rexp(N, 0.01))
ix3 <- 1 + floor(rexp(N, 0.01))
val <- runif(N)
DF <- data.frame(ix1 = ix1, ix2 = ix2, ix3 = ix3, val = val)
DF <- DF[order(DF[,1],DF[,2],DF[,3]),]
DT <- as.data.table(DF)