从长数据帧到宽数组的快速转换
Posted
技术标签:
【中文标题】从长数据帧到宽数组的快速转换【英文标题】:Fast transformation from long data frame to wide array 【发布时间】:2014-05-16 02:24:32 【问题描述】:我有一个因数据集大小而变得具有挑战性的老问题。问题是将数据帧从长矩阵转换为宽矩阵:
set.seed(314)
A <- data.frame(field1 = sample(letters, 10, replace=FALSE),
field2 = sample(toupper(letters), 10, replace=FALSE),
value=1:10)
B <- with(A, tapply(value, list(field1, field2), sum))
这也可以通过 base R 中的旧 reshape 来完成,或者在 plyr 和 reshape2 中更好。在 plyr 中:
daply(A, .(field1, field2), sum)
在重塑2中:
dcast(A, field1 ~ field2, sum)
问题是我的数据框有 30+m 行,field1 至少有 5000 个唯一值,field2 至少有 20000 个唯一值。使用这个大小,plyr 崩溃,reshape2 偶尔崩溃,并且 tapply 非常慢。机器不受限制(48GB、
注意:这个问题不是重复的。我明确提到输出应该是一个宽 array。作为重复引用的答案引用了 dcast.data.table 的使用,它返回一个 data.table。将 data.table 转换为数组是一项非常昂贵的操作。
【问题讨论】:
你见过:***.com/questions/18802257/… 或 ***.com/questions/6902087/… 吗? 希望我的“金锤”重复标记没有为时过早...... +mnel,见上面的评论。这不是重复的问题。 【参考方案1】:FWIW,这是部分使用 data.table
的解决方案(仅用于聚合)。
(编辑:我将dcast.data.table
的答案替换为@BenBolker 的答案,因为它完全避免了该步骤,并且内存和速度都有效 - 如果您正在寻找,请检查修订该解决方案)。
创建一些示例数据(具有类似的规范):
require(data.table) ## >= 1.9.2
set.seed(1L)
N = 30e6L
DT <- data.table(field1 = sample(paste0("F1_", 1:5000), N, TRUE),
field2 = sample(paste0("F2_", 1:20000), N, TRUE),
value = sample(10))
> tables()
# NAME NROW MB COLS KEY
# [1,] DT 30,000,000 574 field1,field2,value
# Total: 574MB
聚合:
system.time(ans <- DT[, list(value=sum(value)), by=list(field1, field2)])
# user system elapsed
# 15.097 3.357 18.454
(编辑后的答案:)然后您可以使用@BenBolker(聪明)的解决方案如下(完全不需要cast
ing):
system.time(
rlabs <- sort(unique(ans$field1))
clabs <- sort(unique(ans$field2))
fans <- matrix(NA,length(rlabs),length(clabs),
dimnames=list(rlabs,clabs))
fans[as.matrix(ans[,1:2, with=FALSE])] <- ans$value
)
# user system elapsed
# 18.630 1.524 20.154
【讨论】:
谢谢,我会介绍的。目前我做一个 dcast.data.table 后跟一个 data.matrix (和一些小的转换)。这应该更快。【参考方案2】:我没有检查速度,但是这种低级方法更好吗? (设置一个充满NA
s 的矩阵并带有适当的边距,并使用2 列矩阵索引填充...)
rlabs <- sort(unique(A$field1))
clabs <- sort(unique(A$field2))
B <- matrix(NA,length(rlabs),length(clabs),
dimnames=list(rlabs,clabs))
B[as.matrix(A[,1:2])] <- A[,3]
如果您可以将其设置为稀疏矩阵,那就太好了,但我假设您的 value
列中的值为零...
【讨论】:
以上是关于从长数据帧到宽数组的快速转换的主要内容,如果未能解决你的问题,请参考以下文章