【问题标题】:efficiently calculate annual cumulative sum有效计算年度累计总和
【发布时间】:2019-01-10 01:21:32
【问题描述】:

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

【问题讨论】:

  • 我会调查 cut 作为创建群组的一种方式,而无需以 fill() - cut(tbl$PERIOD, c(1,4,8,12), labels=c(4,8,12), include.lowest=TRUE) 为例。

标签: r dplyr tidyr


【解决方案1】:

cut 绝对是要走的路。您也可以只计算累积总和,然后保留该期间的最后一行。这避免了聚合步骤。

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

【讨论】:

    【解决方案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
    

    使用相同的逻辑,一个过于复杂的基本 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)
    

    【讨论】:

      猜你喜欢
      • 2020-05-02
      • 2020-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 2015-09-07
      • 2021-06-07
      相关资源
      最近更新 更多