r cumsum per group in dplyr
我开始喜欢
对于演示数据帧,我生成了以下数据:
1 2 3 4 5 6 7 8 | 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) |
这将创建一个数据框,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
然后,我继续创建一个用于绘制的数据框,但是带有一个for循环,我想用一个更干净的东西替换它。
1 2 3 4 5 | 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))) } |
我用这个
1 2 3 | p = ggplot() p = p + geom_line(data=pdf, aes(dates, sales, colour=group)) p + ggtitle("sales per group") |
是否有更好的方法(使用dplyr方法的方法)创建此数据框?我已经看过
啊。在摆弄之后,我似乎找到了它。
1 | pdf = df %>% group_by(group) %>% arrange(dates) %>% mutate(cs = cumsum(sales)) |
输出与有问题的forloop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | > 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))) + } 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 |
使用以下代码行输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | > pdf = df %>% group_by(group) %>% mutate(cs = cumsum(sales)) 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 |
尝试使用
1 2 3 4 | group_by(group) %>% arrange(group) %>% summarise(cs = sum(sales)) %>% mutate(sales_grp = cumsum(cs)) |
我知道这个问/答有点过时,但这可能会帮助任何人在阅读dplyr发布的cumsum()解决方案后被困在我被困的地方
在https://dplyr.tidyverse.org/articles/window-functions.html。和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的问题并发布对我有用的解决方案的尝试;因此,如果我的回答有误,希望您能好一些。我总是尝试从错误中学习。