有效地计算年度累计金额

时间:2019-01-10 01:21:33

标签: r dplyr tidyr

我有一个包含季度交易的数据集。 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查询中的这种累积求和?

2 个答案:

答案 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)