在R语言中实现特定规则的滞后累积求和(lagged cumsum)
问题:计算累积差异值diff_calc
输入数据
df <- tibble( date= seq.Date(as.Date("2021-01-01"), as.Date("2022-02-01"), by = "month"), val1 = c(100, 100, 105, 125, 125, 125, 125, 132, 132, 132, 135, 150, 150, 150), val2 = c(100, 100, 100, 125, 125, 125, 125, 125, 125, 125, 125, 150, 150, 150), diff = val1-val2 )
数据预览:
date val1 val2 diff <date> <dbl> <dbl> <dbl> 1 2021-01-01 100 100 0 2 2021-02-01 100 100 0 3 2021-03-01 105 100 5 4 2021-04-01 125 125 0 5 2021-05-01 125 125 0 6 2021-06-01 125 125 0 7 2021-07-01 125 125 0 8 2021-08-01 132 125 7 9 2021-09-01 132 125 7 10 2021-10-01 132 125 7 11 2021-11-01 135 125 10 12 2021-12-01 150 150 0 13 2022-01-01 150 150 0 14 2022-02-01 150 150 0
需求说明
需要新增列diff_calc,规则如下:
diff_calc是diff中之前出现的唯一值的累积和;- 若连续出现多个唯一的
diff值,取其中的最大值加上按相同规则计算的之前diff值的累积和。
期望输出
output <- tibble( date= seq.Date(as.Date("2021-01-01"), as.Date("2022-02-01"), by = "month"), val1 = c(100, 100, 105, 125, 125, 125, 125, 132, 132, 132, 135, 150, 150, 150), val2 = c(100, 100, 100, 125, 125, 125, 125, 125, 125, 125, 125, 150, 150, 150), diff = val1-val2, diff_calc = c(0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 15, 15, 15) )
输出预览:
date val1 val2 diff diff_calc <date> <dbl> <dbl> <dbl> <dbl> 1 2021-01-01 100 100 0 0 2 2021-02-01 100 100 0 0 3 2021-03-01 105 100 5 0 4 2021-04-01 125 125 0 5 5 2021-05-01 125 125 0 5 6 2021-06-01 125 125 0 5 7 2021-07-01 125 125 0 5 8 2021-08-01 132 125 7 5 9 2021-09-01 132 125 7 5 10 2021-10-01 132 125 7 5 11 2021-11-01 135 125 10 5 12 2021-12-01 150 150 0 15 13 2022-01-01 150 150 0 15 14 2022-02-01 150 150 0 15
解决方案
使用dplyr包实现逻辑,代码如下:
library(dplyr) df_result <- df %>% # 标记diff为0的行,并划分阶段:每次从非0回到0时标记为新阶段 mutate( is_zero = diff == 0, stage = cumsum(is_zero & lag(is_zero, default = TRUE) == FALSE) ) %>% # 按阶段计算该阶段内非0 diff的最大值 group_by(stage) %>% mutate(stage_max = ifelse(all(is_zero), 0, max(diff[!is_zero]))) %>% ungroup() %>% # 计算阶段最大值的累积和,滞后一个阶段用于赋值 mutate( cumulative_sum = lag(cumsum(stage_max), default = 0), # 非0行用上一阶段累积和;0行用累积和加当前阶段最大值 diff_calc = ifelse(is_zero, cumulative_sum + stage_max, cumulative_sum) ) %>% # 清理临时列 select(-is_zero, -stage, -stage_max, -cumulative_sum) print(df_result)
逻辑说明
- 阶段划分:通过
is_zero标记diff为0的行,stage将数据划分为“非0区间+后续0区间”的组合阶段; - 阶段最大值计算:每个阶段内若存在非0 diff,取这些值的最大值,否则为0;
- 累积赋值:
cumulative_sum是阶段最大值的累积和,但滞后一个阶段,确保当前行使用的是之前所有阶段的最大值总和;- 非0行的
diff_calc使用上一阶段的累积和(未到结算点,暂不加入当前阶段最大值); - 0行的
diff_calc使用累积和加上当前阶段的最大值(当前阶段的0区间是上一非0区间的结算点,需加入该区间的最大值)。
内容的提问来源于stack exchange,提问作者costebk08
相关产品推荐
相关产品推荐

