dplyr中每组的r cumsum

can*_*his 18 r ggplot2 dplyr

我开始享受,dplyr但我被困在一个用例.我希望能够cumsum在包中的数据框中应用每个组,但我似乎无法做到正确.

对于演示数据帧,我生成了以下数据:

set.seed(123)

len = 10 
dates = as.Date('2014-01-01') + 1:len
grp_a = data.frame(dates=dates, group='A', sales=rnorm(len))
grp_b = data.frame(dates=dates, group='B', sales=rnorm(len))
grp_c = data.frame(dates=dates, group='C', sales=rnorm(len))
df = rbind(grp_a, grp_b, grp_c)
Run Code Online (Sandbox Code Playgroud)

这会创建一个如下所示的数据框:

        dates group       sales
1  2014-01-02     A -0.56047565
2  2014-01-03     A -0.23017749
3  2014-01-04     A  1.55870831
4  2014-01-05     A  0.07050839
5  2014-01-06     A  0.12928774
6  2014-01-02     B  1.71506499
7  2014-01-03     B  0.46091621
8  2014-01-04     B -1.26506123
9  2014-01-05     B -0.68685285
10 2014-01-06     B -0.44566197
11 2014-01-02     C  1.22408180
12 2014-01-03     C  0.35981383
13 2014-01-04     C  0.40077145
14 2014-01-05     C  0.11068272
15 2014-01-06     C -0.55584113
Run Code Online (Sandbox Code Playgroud)

然后我继续为绘图创建一个数据框,但是有一个for循环,我想用更干净的东西替换.

pdf = data.frame(dates=as.Date(as.character()), group=as.character(), sales=as.numeric())
for(grp in unique(df$group)){
  subs = filter(df, group == grp) %>% arrange(dates)
  pdf = rbind(pdf, data.frame(dates=subs$dates, group=grp, sales=cumsum(subs$sales)))
}
Run Code Online (Sandbox Code Playgroud)

我用它pdf来创建一个情节.

p = ggplot() 
p = p + geom_line(data=pdf, aes(dates, sales, colour=group))
p + ggtitle("sales per group")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

有没有更好的方法(使用dplyr方法的方法)来创建这个数据帧?我看过这个summarize方法,但这似乎聚集了一个来自N个项目的组 - > 1个项目.这个用例似乎打破了我的dplyr流程.有什么建议更好地接近这个吗?

can*_*his 31

啊.摆弄后我似乎找到了它.

pdf = df %>% group_by(group) %>% arrange(dates) %>% mutate(cs = cumsum(sales))
Run Code Online (Sandbox Code Playgroud)

有问题的forloop输出:

> pdf = data.frame(dates=as.Date(as.character()), group=as.character(), sales=as.numeric())
> for(grp in unique(df$group)){
+   subs = filter(df, group == grp) %>% arrange(dates)
+   pdf = rbind(pdf, data.frame(dates=subs$dates, group=grp, sales=subs$sales, cs=cumsum(subs$sales)))
+ }
> pdf
        dates group       sales         cs
1  2014-01-02     A -0.56047565 -0.5604756
2  2014-01-03     A -0.23017749 -0.7906531
3  2014-01-04     A  1.55870831  0.7680552
4  2014-01-05     A  0.07050839  0.8385636
5  2014-01-06     A  0.12928774  0.9678513
6  2014-01-02     B  1.71506499  1.7150650
7  2014-01-03     B  0.46091621  2.1759812
8  2014-01-04     B -1.26506123  0.9109200
9  2014-01-05     B -0.68685285  0.2240671
10 2014-01-06     B -0.44566197 -0.2215949
11 2014-01-02     C  1.22408180  1.2240818
12 2014-01-03     C  0.35981383  1.5838956
13 2014-01-04     C  0.40077145  1.9846671
14 2014-01-05     C  0.11068272  2.0953498
15 2014-01-06     C -0.55584113  1.5395087
Run Code Online (Sandbox Code Playgroud)

使用以下代码行输出:

> pdf = df %>% group_by(group) %>% mutate(cs = cumsum(sales))
> pdf
Source: local data frame [15 x 4]
Groups: group

        dates group       sales         cs
1  2014-01-02     A -0.56047565 -0.5604756
2  2014-01-03     A -0.23017749 -0.7906531
3  2014-01-04     A  1.55870831  0.7680552
4  2014-01-05     A  0.07050839  0.8385636
5  2014-01-06     A  0.12928774  0.9678513
6  2014-01-02     B  1.71506499  1.7150650
7  2014-01-03     B  0.46091621  2.1759812
8  2014-01-04     B -1.26506123  0.9109200
9  2014-01-05     B -0.68685285  0.2240671
10 2014-01-06     B -0.44566197 -0.2215949
11 2014-01-02     C  1.22408180  1.2240818
12 2014-01-03     C  0.35981383  1.5838956
13 2014-01-04     C  0.40077145  1.9846671
14 2014-01-05     C  0.11068272  2.0953498
15 2014-01-06     C -0.55584113  1.5395087
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望将"%>%arrange(dates)"添加到您的单行中,以防您的数据集无法排序,因为您在`for`循环中执行相同操作 (3认同)

小智 7

尝试使用

 group_by(group) %>%
 arrange(group) %>% 
 summarise(cs = sum(sales)) %>%
 mutate(sales_grp = cumsum(cs))
Run Code Online (Sandbox Code Playgroud)

我知道这个 Q/A 有点过时,但这可能会帮助任何人在阅读 dplyr 在https://dplyr.tidyverse.org/articles/window-functions.html上发布的 cumsum() 解决方案后陷入困境。和http://www.sthda.com/english/articles/17-tips-tricks/57-dplyr-how-to-add-cumulative-sums-by-groups-into-a-data-framee/

上面链接中发布的解决方案不会按组求和。该代码仅按顺序添加下一行——这不是分组累积和。我认为 OP 正在寻找 A 组、B 组和 C 组的销售额总和,并将每个组的总数添加到下一个组中 - OP 案例中的总 n() 应该是 3 而不是 15,并且具有分组累积和()。例如,如果您试图计算 10 月底之前发生的年度销售额的百分比,那么这将很有帮助,例如您想要按月计算的销售额总和,然后按顺序计算全年的总销售额。

因此,您需要首先汇总每个组的值,然后按组的顺序汇总它们。PS——这是我第一次尝试回答有关 SO 的问题并发布对我有用的解决方案;所以如果我的回答有误,希望您能多多指教。我总是尝试从错误中吸取教训。