我有一个包含季度交易的数据集。 PERIOD
代表交易的四分之一,INCREM
代表增量的金额。
tbl <- data.frame(PERIOD = c(2,3,6,10,11),
INCREM = c(10,50,-30,-10,-20))
我想获取年度累计金额(因此,在第4、8、12期间的累计金额)。
library(dplyr)
library(tidyr)
tbl %>%
mutate(CUMSUM = cumsum(INCREM)) %>%
select(-INCREM) %>%
mutate(PERIOD = factor(PERIOD, 1:12)) %>%
complete(PERIOD) %>%
fill(CUMSUM) %>%
mutate(PERIOD = as.numeric(PERIOD)) %>%
filter(PERIOD %% 4 == 0)
结果:
PERIOD CUMSUM
1 4 60
2 8 30
3 12 0
这有效,但是效率不高。原始数据集为5行,最终数据集为3行,但是在dplyr
链的中间(在fill()
之后),数据集为12行。
是否有更有效的方法来获取年度累计金额?
此外,我的实际数据来自数据库查询。您认为对我来说,在使用R进行操作之前,最好先处理一下SQL查询中的这种累积求和?
答案 0 :(得分:3)
切割绝对是必经之路。您也可以只计算累计总和,然后保留期间的最后几行。这样可以避免聚合步骤。
tbl$prd <- cut(tbl$PERIOD, c(1,4,8,Inf), labels=c(4,8,12))
tbl$cumsum <- cumsum(tbl$INCREM)
tbl[!duplicated(tbl$prd, fromLast=TRUE),c("prd","cumsum")]
# prd cumsum
# 2 4 60
# 3 8 30
# 5 12 0
答案 1 :(得分:2)
按照@thelatemail的建议,您可以使用cut
创建组,然后在每个组中使用sum
,最后在所有值上使用cumsum
。
library(dplyr)
tbl %>%
group_by(quarter = cut(PERIOD, c(1,4,8,Inf), labels=c(4,8,12))) %>%
summarise(CUMSUM = sum(INCREM)) %>%
ungroup() %>%
mutate(CUMSUM = cumsum(CUMSUM))
# quarter CUMSUM
# <fct> <dbl>
#1 4 60
#2 8 30
#3 12 0
使用相同的逻辑将过于复杂的base R方法拟合到一行是
transform(aggregate(INCREM~PERIOD,
transform(tbl, PERIOD = cut(PERIOD, c(1,4,8,Inf), labels=c(4,8,12))), sum),
INCREM = cumsum(INCREM))
# PERIOD INCREM
#1 4 60
#2 8 30
#3 12 0
这实际上是
tbl$PERIOD <- cut(tbl$PERIOD, c(1,4,8,Inf), labels=c(4,8,12))
tbl1 <- aggregate(INCREM~PERIOD, tbl, sum)
tbl1$INCREM <- cumsum(tbl1$INCREM)