按组计算累积总和 (cumsum)

Calculate cumulative sum (cumsum) by group

提问人:Rock 提问时间:5/31/2013 最后编辑:HenrikRock 更新时间:6/5/2022 访问量:61230

问:

使用数据框:

df <- data.frame(id = rep(1:3, each = 5)
                 , hour = rep(1:5, 3)
                 , value = sample(1:15))

我想添加一个与以下列匹配的累积总和列:id

df
   id hour value csum
1   1    1     7    7
2   1    2     9   16
3   1    3    15   31
4   1    4    11   42
5   1    5    14   56
6   2    1    10   10
7   2    2     2   12
8   2    3     5   17
9   2    4     6   23
10  2    5     4   27
11  3    1     1    1
12  3    2    13   14
13  3    3     8   22
14  3    4     3   25
15  3    5    12   37

我怎样才能有效地做到这一点?谢谢!

r cumsum

评论


答:

65赞 IRTFM 5/31/2013 #1
df$csum <- ave(df$value, df$id, FUN=cumsum)

ave如果您想要一个与现有向量长度相等的按组向量,则是“首选”函数,并且可以仅从这些子向量计算。如果需要基于多个“并行”值进行分组处理,则基本策略是 。do.call(rbind, by(dfrm, grp, FUN))

评论

0赞 Rock 5/31/2013
unique.default(x, nmax = nmax) 中的错误:unique() 仅适用于向量
1赞 IRTFM 5/31/2013
我一直忘记......需要命名 FUN 参数。
4赞 Brian D 11/19/2016
请注意,如果多个列定义每个唯一行,则可以添加其他变量。例如,.iddf$csum <- ave(df$value, df$id1, df$id2, FUN=cumsum)
0赞 smci 8/30/2019
@42- 自 2013 年起被封存(已经六年前)。你应该推荐 /tidyverse/plyrdplyrdata.table
1赞 IRTFM 8/30/2019
我没有说我不喜欢.我说我在现在删除的评论中提到了它。我投票支持A5C1D2H2I1M1N2O1R2T1的解决方案,我承认这是非常清楚的data.table
8赞 Didzis Elferts 5/31/2013 #2

使用库 .plyr

library(plyr)
ddply(df,.(id),transform,csum=cumsum(value))
30赞 A5C1D2H2I1M1N2O1R2T1 5/31/2013 #3

为了添加到替代方案中,的语法很好:data.table

library(data.table)
DT <- data.table(df, key = "id")
DT[, csum := cumsum(value), by = key(DT)]

或者,更紧凑地说:

library(data.table)
setDT(df)[, csum := cumsum(value), id][]

以上将:

  • 通过引用将 转换为data.framedata.table
  • 计算按 id 分组的值的累积总和,并按引用进行分配
  • 打印(最后一个)整个操作的结果[]

“df”现在将是一个带有“csum”列的 a。data.table

27赞 tjebo 11/13/2017 #4

使用 dplyr::

require(dplyr)
df %>% group_by(id) %>% mutate(csum = cumsum(value))

评论

3赞 Kathiravan Meeran 11/15/2018
嘿,我试过你的方法。不知何故,分组无法正常工作。它对所有数据点进行 cumsum 而不进行分组。有什么建议吗?
0赞 tjebo 11/15/2018
有时,在这些情况下,启动新的 R 会话会有所帮助。在示例数据上尝试我的代码。
3赞 user3602585 4/10/2019
只是一个更新,您可能有一个已加载的包。显式引用也将修复它: ''' df %>% group_by(id) %>% dplyr::mutate(csum = cumsum(value)) '''plyrdplyr
0赞 Ben 6/30/2023
我对 dplyr 的明确引用并没有产生准确的分组结果;使用 DIDave()
2赞 Mohamed Desouky 6/5/2022 #5

使用基本 R

df <- data.frame(id = rep(1:3, each = 5)
                 , hour = rep(1:5, 3)
                 , value = sample(1:15))

transform(df , csum = ave(value , id , FUN = cumsum))
#>    id hour value csum
#> 1   1    1     4    4
#> 2   1    2    12   16
#> 3   1    3    13   29
#> 4   1    4     6   35
#> 5   1    5     5   40
#> 6   2    1    15   15
#> 7   2    2     1   16
#> 8   2    3     2   18
#> 9   2    4     8   26
#> 10  2    5     9   35
#> 11  3    1    11   11
#> 12  3    2     7   18
#> 13  3    3    10   28
#> 14  3    4     3   31
#> 15  3    5    14   45

reprex 软件包 (v2.0.1) 于 2022-06-05 创建