R语言按分组基于前一行值递推计算填充data.frame的NA值
R按分组递推填充value列缺失值
问题说明
现有测试数据框结构如下:
df <- data.frame(id = c(12345,12345,12345,221,221,221), range_key = c('2022 Q2','2022 Q3','2023 Q4','2022 Q2','2023 Q3','2023 Q4'), country = c('US','US','US','CA','CA','CA'), value = c(10,8,NA,5,NA,NA), pct = c(-0.2,-0.2,-0.2,-0.12,-0.12,-0.12))
处理要求:
- 按
id、country字段对数据分组 - 每个分组内按时间顺序逐行处理,
value列的缺失值用前一行的value计算填充 - 计算逻辑:
当前行value = 前一行value + 前一行value * pct,化简后等价于当前行value = 前一行value * (1 + pct)(你贴的原始公式存在未闭合的括号,按逻辑补全后就是上述形式)
实现代码
方案1:dplyr 递推实现(推荐,代码简洁不易错)
核心是用accumulate2做逐行累积计算,遇到已有非NA值就直接保留,遇到NA就按公式用上一个有效值推导,注意一定要先按季度字段排序,避免行顺序错乱导致计算错误:
library(dplyr) df_res <- df %>% arrange(id, country, range_key) %>% group_by(id, country) %>% mutate( value = accumulate2( value, pct, ~ ifelse(is.na(.y), ..1 * (1 + ..3), .y) ) %>% unlist() ) %>% ungroup()
运行后输出结果:
# A tibble: 6 × 5 id range_key country value pct <dbl> <chr> <chr> <dbl> <dbl> 1 221 2022 Q2 CA 5 -0.12 2 221 2023 Q3 CA 4.4 -0.12 3 221 2023 Q4 CA 3.52 -0.12 4 12345 2022 Q2 US 10 -0.2 5 12345 2022 Q3 US 8 -0.2 6 12345 2023 Q4 US 6.4 -0.2
计算逻辑验证:
- CA组(id=221):2023 Q3的value = 5*(1-0.12) = 4.4;2023 Q4的value = 4.4*(1-0.12)=3.52
- US组(id=12345):2023 Q4的value = 8*(1-0.2)=6.4,完全符合要求。
方案2:基础R实现(无需安装第三方包)
不想加载tidyverse包的话,可以拆分分组后写循环逐行处理:
# 按分组字段拆分数据 group_df <- split(df, list(df$id, df$country), drop = TRUE) # 逐组递推填充 group_res <- lapply(group_df, function(sub) { # 先按季度排序保证顺序正确 sub <- sub[order(sub$range_key), ] # 从第二行开始逐行判断填充 for (i in 2:nrow(sub)) { if (is.na(sub$value[i])) { sub$value[i] <- sub$value[i-1] * (1 + sub$pct[i]) } } sub }) # 合并所有分组结果 df_res <- do.call(rbind, group_res) rownames(df_res) <- NULL
运行结果和dplyr方案完全一致。
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

