如何用对应行x值修正分组移动平均列x.mv的NA填充问题?
解决分组移动平均前两行NA替换为对应行x值的问题
首先,我得先点明你遇到的核心问题:你之前用fill = x[1:2]的写法,一是没考虑分组后的作用域(取的是整个数据框的前两个x值,而非当前分组内的),二是zoo::rollmean的fill参数本身就不是用来动态替换对应行x值的,它只会用固定值填充所有需要补全的位置,这才导致所有NA都被填充成同一个x值。
下面给你两种简洁且正确的解决方案:
方案1:先算移动平均,再分组替换前两行的NA
这种方法逻辑直观,先得到带NA的移动平均列,再在每个分组内精准替换前两行的NA为对应行的x值:
library(dplyr) library(zoo) # 先生成测试数据 set.seed(123) df <- data.frame( loc.id = rep(c(1:3), each = 4*10), year = rep(rep(c(1980:1983), each = 10), times = 3), day = rep(1:10, times = 3*4), x = sample(123:200, 4*3*10, replace = T) ) # 处理移动平均并替换NA df_processed <- df %>% group_by(loc.id, year) %>% mutate( # 先计算右对齐3日移动平均,保留前两行的NA x.mv = rollmean(x, 3, fill = NA, align = "right"), # 在当前分组内,把前两行的x.mv替换为对应行的x值 x.mv = replace(x.mv, row_number() %in% 1:2, x[row_number() %in% 1:2]) ) %>% ungroup()
方案2:用case_when写更易读的规则
如果你偏好可读性更强的代码,可以用case_when明确判断位置并赋值:
df_processed <- df %>% group_by(loc.id, year) %>% mutate( x.mv = rollmean(x, 3, fill = NA, align = "right"), x.mv = case_when( row_number() <= 2 ~ x, # 前两行直接用x本身 TRUE ~ x.mv # 其他行保留移动平均结果 ) ) %>% ungroup()
再说说你原代码的问题
- 作用域错误:在
group_by之后,x[1:2]指向的是整个df的前两个x值,而非当前分组内的前两个x值,所以所有分组的NA都会被填充成全局的x[1]和x[2],而不是自己组内对应行的值。 fill参数的逻辑限制:rollmean的fill参数是用来填充移动平均无法计算的位置,它只会用你提供的固定值(或重复向量)统一填充,不会动态匹配当前行的x值。
内容的提问来源于stack exchange,提问作者89_Simple
相关产品推荐
相关产品推荐

