xbs*_*bsd 22 parallel-processing r data.table
这个问题适用于创建"宽"表,类似于您可以使用reshape2中的dcast创建的表.我知道之前已经讨论了很多次,但我的问题是如何使这个过程更有效率.我在下面提供了几个例子,这些例子可能会使问题看起来很冗长,但大多数只是用于基准测试的测试代码
从一个简单的例子开始,
> z <- data.table(col1=c(1,1,2,3,4), col2=c(10,10,20,20,30),
col3=c(5,2,2.3,2.4,100), col4=c("a","a","b","c","a"))
> z
col1 col2 col3 col4
1: 1 10 5.0 a # col1 = 1, col2 = 10
2: 1 10 2.0 a # col1 = 1, col2 = 10
3: 2 20 2.3 b
4: 3 20 2.4 c
5: 4 30 100.0 a
Run Code Online (Sandbox Code Playgroud)
我们需要创建一个"宽"表,它将col4列的值作为列名,并将col1和col2的每个组合的和(col3)值组合在一起.
> ulist = unique(z$col4) # These will be the additional column names
# Create long table with sum
> z2 <- z[,list(sumcol=sum(col3)), by='col1,col2,col4']
# Pivot the long table
> z2 <- z2[,as.list((sumcol[match(ulist,col4)])), by=c("col1","col2")]
# Add column names
> setnames(z2[],c("col1","col2",ulist))
> z2
col1 col2 a b c
1: 1 10 7 NA NA # a = 5.0 + 2.0 = 7 corresponding to col1=1, col2=10
2: 2 20 NA 2.3 NA
3: 3 20 NA NA 2.4
4: 4 30 100 NA NA
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,虽然上面的方法适用于较小的表,但实际上不可能在非常大的表上运行它们(除非你可以等待x小时).
我相信这可能与这样一个事实有关:旋转/宽表的大小比原始表大得多,因为宽表中的每一行都有n列对应于枢轴列的唯一值,无论是否有与该单元格对应的任何值(这些是上面的NA值).因此,新表的大小通常是原始"长"表的2倍.
我的原始表有大约5亿行,大约20个唯一值.我试图仅使用500万行来运行上面的内容,并且它需要永远在R中(等待它完成的时间太长).
出于基准测试目的,该示例(使用500万行) - 使用运行多线程的生产rdbms系统在大约1分钟内完成.它使用KDB +/Q(http://www.kx.com)使用单核在大约8"秒内完成.这可能不是一个公平的比较,但给出一种感觉,即使用替代方法可以更快地完成这些操作.KDB +没有稀疏行,因此它为所有单元分配内存,并且仍然比我尝试过的任何其他内容快得多.
然而,我需要的是一个R解决方案 :)到目前为止,我还没有找到一种执行类似操作的有效方法.
如果您有经验并且可以反思任何替代/更优化的解决方案,我会有兴趣知道相同的.下面提供了示例代码.您可以更改n的值以模拟结果.枢轴列(列c3)的唯一值已固定为25.
n = 100 # Increase this to benchmark
z <- data.table(c1=sample(1:10000,n,replace=T),
c2=sample(1:100000,n,replace=T),
c3=sample(1:25,n,replace=T),
price=runif(n)*10)
c3.unique <- 1:25
z <- z[,list(sumprice=sum(price)), by='c1,c2,c3'][,as.list((sumprice[match(c3.unique,c3)])), by='c1,c2']
setnames(z[], c("c1","c2",c3.unique))
Run Code Online (Sandbox Code Playgroud)
谢谢,
对于n=1e6以下需要大约10秒的平原dcast和大约4秒dcast.data.table:
library(reshape2)
dcast(z[, sum(price), by = list(c1, c2, c3)], c1 + c2 ~ c3)
# or with 1.8.11
dcast.data.table(z, c1 + c2 ~ c3, fun = sum)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4965 次 |
| 最近记录: |