【问题标题】:Aggregating duplicate rows by taking sum通过求和聚合重复行
【发布时间】:2014-04-06 11:19:04
【问题描述】:

继续我的问题:
1.Identifying whether a set of variables uniquely identifies each row of the data or not;
2.Tagging all rows that are duplicates in terms of a given set of variables,
我现在想根据给定的一组变量汇总/合并所有重复行,方法是取它们的总和。

解决方案 1:

有一些关于如何做到这一点的指导here,但是当有大量级别的变量构成索引时,推荐的ddply方法很慢,因为在这种情况下我试图用一组给定的变量标记所有重复项。

# Values of (f1, f2, f3, f4) uniquely identify observations
dfUnique = expand.grid(f1 = factor(1:16),
                       f2 = factor(1:41),
                       f3 = factor(1:2),
                       f4 = factor(1:104))

# sample some extra rows and rbind them
dfDup = rbind(dfUnique, dfUnique[sample(1:nrow(dfUnique), 100), ])

# dummy data 
dfDup$data = rnorm(nrow(dfDup))

# aggregate the duplicate rows by taking the sum
dfDupAgg = ddply(dfDup, .(f1, f2, f3, f4), summarise, data = sum(data))

解决方案 2:

第二种解决方案是使用data.table,按照here的建议,我可以这样做

# data.table solution
indexVars = paste0('f', 1:4, sep = '')
dtDup = data.table(dfDup, key = indexVars)
dtDupAgg = dtDup[, list(data = sum(data)), by = key(dtDup)]

我有几个问题:
1.有没有办法让ddply版本更快?
2.data.table 正确吗?我想检查一下,因为我是 data.table 的新手。

【问题讨论】:

    标签: r data.table plyr


    【解决方案1】:

    关于您的data.table 解决方案,您不需要设置键 进行聚合操作。你可以直接这样做:

    indexVars = paste0('f', 1:4, sep = '')
    dtDup <- as.data.table(dfDup) ## faster than data.table(.)
    dtDupAgg = dtDup[, list(data = sum(data)), by = c(indexVars)]
    

    data.table 1.9.2+ 版还实现了一个函数setDT,它可以将data.frames 转换为data.tables 通过引用(这意味着没有副本,因此几乎需要没有时间进行转换,尤其适用于大型 data.frames)。

    所以,不要这样做:

    dtDup <- as.data.table(dfDup)
    dtDup[...]
    

    你可以这样做:

    ## data.table v1.9.2+
    setDT(dfDup) ## faster than as.data.table(.)
    dfDup[...]   ## dfDup is now a data.table, converted by reference
    

    在您的第一个问题上,plyr 并不以速度着称。查看Why is plyr so slow?(以及那里的许多信息丰富的 cmets)了解更多信息。

    也许您可能对dplyr 感兴趣,它比plyr 快几个数量级,但仍然比data.table 慢,恕我直言。这是等效的dplyr 版本:

    dfDup %.% group_by(f1, f2, f3, f4) %.% summarise(data = sum(data))
    

    这是data.tabledplyr 之间的数据基准测试(所有时间至少连续运行三个):

    ## data.table v1.9.2+
    system.time(ans1 <- dtDup[, list(data=sum(data)), by=c(indexVars)])
    #  user  system elapsed 
    # 0.049   0.009   0.057 
    
    ## dplyr (commit ~1360 from github)
    system.time(ans2 <- dfDup %.% group_by(f1, f2, f3, f4) %.% summarise(data = sum(data)))
    #  user  system elapsed 
    # 0.374   0.013   0.389 
    

    我真的没有耐心运行plyr 版本(第一次运行93 秒后停止)。如您所见,dplyrplyr 快得多,但比这里的 data.table 慢约 7 倍。


    检查结果是否相等确定:

    all.equal(as.data.frame(ans1[order(f1,f2,f3,f4)]), 
              as.data.frame(ans2))
    # [1] TRUE
    

    HTH

    【讨论】:

    • 对于ddply 计时(2.8 GHz Core i7 16MB RAM MacBook Pro)system.time(dfDupAgg2 &lt;- ddply(dfDup, .(f1, f2, f3, f4), summarise, data = sum(data))) user [109.305] system [19.276] elapsed [128.528]group_by 采用(平均)~0.21 :-)
    猜你喜欢
    • 2014-09-30
    • 2012-12-17
    • 1970-01-01
    • 2020-08-31
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多