R语言基于另一dataframe按三条件实现rolling sum计算
R实现多维度条件滚动求和(等效Excel SUMIF)
核心逻辑
不需要写复杂循环逐行匹配,直接用分组累计求和+维度表关联的方式就能实现,规则完全对齐需求:同公司、同账户下,所有日期小于等于当前统计日的交易金额求和,没有交易记录的公司/账户组合自动补0占位。
可直接运行的实现代码
依赖dplyr、tidyr、lubridate三个包,未安装的话先跑install.packages(c("dplyr","tidyr","lubridate"))
library(dplyr) library(tidyr) library(lubridate) # ---------------------- # 1. 初始化示例数据 # ---------------------- # 原始交易流水表 trans_df <- tibble( trans_date = ymd(c("2021-01-01","2021-01-01","2021-01-01", "2021-01-02","2021-01-02","2021-01-02")), company = rep("A公司",6), account = c("a","a","b","a","b","b"), amount = c(100, 200, 150, 50, 80, 120) ) # 日终余额表维度骨架:所有需要统计的日期、公司、账户的全组合,这里包含需要占位的B公司 balance_dim <- expand_grid( stat_date = seq.Date(ymd("2021-01-01"), ymd("2021-01-02"), by = "day"), company = c("A公司","B公司"), account = c("a","b") ) # ---------------------- # 2. 计算分组累计余额 # ---------------------- cum_trans <- trans_df %>% # 先聚合同一天同公司同账户的多笔交易,避免重复累计 group_by(trans_date, company, account) %>% summarise(daily_total = sum(amount), .groups = "drop_last") %>% # 按公司、账户分组,按日期升序做累计求和 arrange(trans_date, .by_group = TRUE) %>% mutate(balance = cumsum(daily_total)) %>% ungroup() # ---------------------- # 3. 关联维度表得到最终结果 # ---------------------- result <- balance_dim %>% left_join( cum_trans %>% select(trans_date, company, account, balance), by = c("stat_date" = "trans_date", "company", "account") ) %>% group_by(company, account) %>% arrange(stat_date, .by_group = TRUE) %>% # 无交易日余额沿用上一日数值,首日无交易填0 fill(balance, .direction = "down") %>% replace_na(list(balance = 0)) %>% ungroup()
结果说明
运行后输出的result完全符合预期:
- 2021-01-01:A公司a账户余额300、b账户150;B公司a、b账户余额均为0
- 2021-01-02:A公司a账户余额350、b账户350;B公司a、b账户余额均为0
如果不需要保留无交易的日期断层,只需要统计有交易发生的日期+指定占位维度,删掉
fill那行代码,直接把NA替换为0即可。如果统计日期范围更长,只要修改balance_dim里的stat_date序列就行,不需要改核心计算逻辑。
内容的提问来源于stack exchange,提问作者Matias Ochoa
相关产品推荐
相关产品推荐

