如何用Tidyverse将NA替换为前序值的累积均值?
用累积均值替换NA值(按组处理)
以下提供两种符合需求的实现方案,分别对应不包含已填充值和包含已填充值的累积均值计算逻辑:
方案1:不包含已填充值的累积均值替换
该方案仅使用原始非NA值计算当前位置之前的均值,忽略已填充的NA结果,适合需要保留原始数据基准的场景。
library(tidyverse) iname <- rep('a', 10) itime <- 1:10 ival <- c(1, 2, 3, NA, 5, 6, NA, 8, 9, 10) ds <- tibble(iname, itime, ival) result1 <- ds %>% group_by(iname) %>% mutate( # 计算到当前位置前的非NA值累积总和 cum_sum = lag(cumsum(ifelse(is.na(ival), 0, ival))), # 计算到当前位置前的非NA值数量 cum_n = lag(cumsum(!is.na(ival))), # 替换NA为累积均值,非NA值保留原数据 ival = ifelse(is.na(ival), cum_sum / cum_n, ival) ) %>% select(-cum_sum, -cum_n) # 移除中间计算辅助列 print(result1)
输出结果:
# A tibble: 10 × 3 # Groups: iname [1] iname itime ival <chr> <int> <dbl> 1 a 1 1 2 a 2 2 3 a 3 3 4 a 4 2 5 a 5 5 6 a 6 6 7 a 7 3.4 8 a 8 8 9 a 9 9 10 a 10 10
方案2:包含已填充值的累积均值替换
该方案会把之前填充的NA值纳入后续的累积均值计算,适合需要模拟"实时填充后更新基准"的场景。
result2 <- ds %>% group_by(iname) %>% mutate( ival = accumulate(ival, function(prev, curr) { if (is.na(curr)) { # 计算之前所有值的均值(包括已填充的结果) mean(prev) } else { # 非NA值直接保留,同时将其加入后续计算的序列 c(prev, curr) } }) %>% map_dbl(last) # 提取每个迭代步骤的最终值作为当前行结果 ) print(result2)
输出结果:
# A tibble: 10 × 3 # Groups: iname [1] iname itime ival <chr> <int> <dbl> 1 a 1 1 2 a 2 2 3 a 3 3 4 a 4 2 5 a 5 5 6 a 6 6 7 a 7 3.17 8 a 8 8 9 a 9 9 10 a 10 10
补充说明
- 两种方案均支持按
iname分组处理,多组数据会独立计算各自的累积均值。 - 方案1计算效率更高,适合大数据集;方案2逻辑更直观,但迭代处理的性能稍弱。
内容的提问来源于stack exchange,提问作者Aureliano Guedes
相关产品推荐
相关产品推荐

