使用ddply的cumsum

时间:2013-02-21 10:11:33

标签: r aggregate plyr

如果更容易,我需要在ddply或者聚合中使用group by。我不确定如何做到这一点,因为我需要使用cumsum作为我的聚合函数。这就是我的数据:

level1      level2  hour     product 
A           tea     0          7
A           tea     1          2
A           tea     2          9
A           coffee  17         7
A           coffee  18         2
A           coffee  20         4
B           coffee  0          2
B           coffee  1          3
B           coffee  2          4
B           tea     21         3
B           tea     22         1

预期产出:

A     tea     0   7
A     tea     1   9
A     tea     2   18
A     coffee  17  7
A     coffee  18  9
A     coffee  20  13
B     coffee  0   2
B     coffee  1   5
B     coffee  2   9
B     tea     21  3
B     tea     22  4

我尝试使用

ddply(dd,c("level1","level2","hour"),summarise,cumsum(product))

但是这并不总结我认为是因为小时栏被用于分组而被它拆分......我想..我不确定我是否完全理解聚合如何在这里工作。有什么方法可以使用aggregate或ddply获得所需的输出吗?

2 个答案:

答案 0 :(得分:16)

以下是使用avewithin的基础R的解决方案:

within(mydf, {
  cumsumProduct <- ave(product, level1, level2, FUN = cumsum)
})
#    level1 level2 hour product cumsumProduct
# 1       A    tea    0       7             7
# 2       A    tea    1       2             9
# 3       A    tea    2       9            18
# 4       A coffee   17       7             7
# 5       A coffee   18       2             9
# 6       A coffee   20       4            13
# 7       B coffee    0       2             2
# 8       B coffee    1       3             5
# 9       B coffee    2       4             9
# 10      B    tea   21       3             3
# 11      B    tea   22       1             4

当然,如果您想删除现有的产品列,可以将命令更改为以下内容以覆盖当前的“产品”列:

within(mydf, {
  product <- ave(product, level1, level2, FUN = cumsum)
})

您当前的方法无法正常工作,因为您已将“小时”作为您的分组变量之一。换句话说,它看到“A +茶+ 0”的组合与“A +茶+ 1”不同,但是根据您想要的输出,您似乎只想要“A +茶”的组合是基。

aggregate无法按预期工作,因为它会将所有内容压缩为data.frame,其行数与“level1”和“level2”的唯一组合数相同,在这种情况下,4行。汇总列为list。这些值是正确的,但它没那么有用。

这是aggregate及其输出:

> aggregate(product ~ level1 + level2, mydf, cumsum)
  level1 level2  product
1      A coffee 7, 9, 13
2      B coffee  2, 5, 9
3      A    tea 7, 9, 18
4      B    tea     3, 4

答案 1 :(得分:7)

您应该使用transform代替summarise

# you should probably order your `level2` first
dd$level2 <- factor(dd$level2, levels=c("tea", "coffee"))
# and transform using level1 and level2 alone, not hour
# if you use hour, the groups will be for each row
ddply(dd, .(level1, level2), transform, product=cumsum(product))

#    level1 level2 hour product
# 1       A    tea    0       7
# 2       A    tea    1       9
# 3       A    tea    2      18
# 4       A coffee   17       7
# 5       A coffee   18       9
# 6       A coffee   20      13
# 7       B    tea   21       3
# 8       B    tea   22       4
# 9       B coffee    0       2
# 10      B coffee    1       5
# 11      B coffee    2       9