如何在R中实现基于列b值的列a滚动求和并修正重置时机错误
解决动态窗口滚动求和及指定行开始的分组累计求和问题
一、动态窗口大小的滚动求和
你当前用ave结合固定分组的方式不符合需求,因为你需要的是滚动窗口求和(窗口随每行滑动),而非固定块分组的累计求和。
方法1:使用slider包(简洁高效)
首先构造目标数据框:
df <- data.frame( a = c(1, 2, 3, 4, 1, 2, 3, 4), b = rep(3, 8) )
利用slider包的slide_dbl函数,支持每行使用列b的动态值作为窗口大小:
library(slider) df$CumSum <- slide_dbl( .x = df$a, .f = ~sum(.x), .before = df$b - 1, # 窗口包含当前行及前面的b-1行 .complete = FALSE # 窗口行数不足时仍计算现有行的和 )
运行后得到完全符合预期的结果:
a b CumSum 1 1 3 1 2 2 3 3 3 3 3 6 4 4 3 9 5 1 3 8 6 2 3 7 7 3 3 6 8 4 3 9
方法2:基础R实现(无需额外包)
通过循环每行手动控制窗口起始位置,计算窗口内的求和:
df$CumSum <- sapply(seq_len(nrow(df)), function(i) { # 确保窗口起始行不小于数据框第一行 start_row <- max(1, i - df$b[i] + 1) # 对窗口内的a值求和 sum(df$a[start_row:i]) })
此方法无需安装额外包,同样能得到目标结果。
二、从指定行开始,每X行重置累计求和
核心思路是先构造正确的分组变量,再用ave实现分组累计求和,以下是封装好的函数:
reset_cumsum <- function(data, target_col, reset_interval, start_row) { # 初始化分组向量 group <- rep(0, nrow(data)) # 将指定行之前的部分单独作为一组 if (start_row > 1) { group[1:(start_row - 1)] <- 1 } # 对指定行及之后的部分,每reset_interval行分为一组 rows_after <- seq(start_row, nrow(data)) group[rows_after] <- ceiling((rows_after - start_row + 1) / reset_interval) + 1 # 计算分组累计求和 data$cum_reset <- ave(data[[target_col]], group, FUN = cumsum) return(data) }
示例用法
比如你需要从第2行开始,每3行重置一次累计求和:
df <- reset_cumsum(df, target_col = "a", reset_interval = 3, start_row = 2)
运行结果:
a b CumSum cum_reset 1 1 3 1 1 2 2 3 3 2 3 3 3 6 5 4 4 3 9 9 5 1 3 8 1 6 2 3 7 3 7 3 3 6 6 8 4 3 9 4
其中cum_reset列就是从第2行开始,每3行重置一次的累计求和结果。
内容的提问来源于stack exchange,提问作者Alisha Dcosta
相关产品推荐
相关产品推荐

