R中存在分组缺失时如何按组计算列的累计和
问题原因
原有代码失效的核心原因是:原始数据仅保留了有实际观测的(location, type)组合行,若某分组在指定日期无观测,对应日期下该分组的行完全不存在,group_by+cumsum只会在分组现有行的基础上计算累计值,不会自动补齐缺失日期的行,自然无法输出缺失分组在对应日期的累计结果。
解决方法
使用tidyr::complete()先补全所有「日期×地点×类型」的全量交叉组合,把缺失组合的NOV值填充为0,再按分组计算累计和即可,完全匹配需求:
- 每个日期下所有location、type的组合都会保留
- 当日无观测的分组NOV记为0
- 累计和会自动延续该分组的历史累计结果,不会中断
可直接运行的代码
library(tidyverse) d_new <- df %>% # 先按日期升序排列,避免累计顺序错乱 arrange(date) %>% # 补全三个维度的所有交叉组合,缺失的NOV填充为0 complete(date, location, type, fill = list(NOV = 0)) %>% # 按分组计算累计和,带空格的列名需要用反引号包裹 group_by(location, type) %>% mutate(`CUMSUM NOV` = cumsum(NOV)) %>% ungroup()
大数据量优化
如果数据集行数超过百万,可提前提取三个维度的唯一值传入complete(),减少函数内部匹配的开销,提升运行速度:
# 提前提取全量维度值 all_date <- unique(df$date) all_location <- unique(df$location) all_type <- unique(df$type) d_new <- df %>% arrange(date) %>% complete( date = all_date, location = all_location, type = all_type, fill = list(NOV = 0) ) %>% group_by(location, type) %>% mutate(`CUMSUM NOV` = cumsum(NOV)) %>% ungroup()
注意事项
- 计算累计和前必须确保日期按升序排列,否则累计结果会出现顺序错误
- R中带空格的列名必须用反引号
`包裹,否则会触发语法报错 - 若最终不需要保留补全的NOV=0的原始观测行,只需要给原数据匹配累计值,可以在计算完成后加一行
semi_join(df, by = c("date", "location", "type"))即可回到原数据的行结构,同时带正确的累计值。
内容的提问来源于stack exchange,提问作者Shapa
相关产品推荐
相关产品推荐

