如何用dplyr/tidyr按组仅填充非NA值上方的首个NA
按组仅填充非NA值上方第一个NA的实现方法
需求说明
对分组数据执行定向填充:仅将每个非NA值正上方紧邻的那个NA替换为该非NA值,其余NA保持不变,填充方向为"向上"(仅填充目标值的前一行)。tidyr::fill()无法直接实现该逻辑,因为它会填充所有上方连续的NA。
示例数据
df <- data.frame(g=c(1,1,1,1,1,1, 2,2,2,2,2,2,2),v=c(NA,NA,5,NA,8,NA, 1,1,NA,2,NA,NA,3))
原始数据:
g v 1 1 NA 2 1 NA 3 1 5 4 1 NA 5 1 8 6 1 NA 7 2 1 8 2 1 9 2 NA 10 2 2 11 2 NA 12 2 NA 13 2 3
期望输出:
g v 1 1 NA 2 1 5 3 1 5 4 1 8 5 1 8 6 1 NA 7 2 1 8 2 1 9 2 2 10 2 2 11 2 NA 12 2 3 13 2 3
解决方案(基于dplyr)
通过分组标记目标行,结合lead()函数实现精准填充:
library(dplyr) result_df <- df %>% group_by(g) %>% mutate( # 标记需要填充的行:非NA值的上一行 fill_target = row_number() %in% (which(!is.na(v)) - 1), # 对标记行,用下一行的非NA值填充 v = ifelse(fill_target, lead(v), v) ) %>% select(-fill_target) %>% # 移除辅助标记列 ungroup() print(result_df)
代码解释
group_by(g):按分组变量g拆分数据,确保每个组内独立处理which(!is.na(v)):定位组内所有非NA值的行号,减1得到它们的上一行行号fill_target:生成布尔标记,标记出需要填充的行lead(v):获取当前行的下一行v值,对标记行替换原NA,非标记行保留原值select(-fill_target):清理辅助列,ungroup()取消分组
运行代码后即可得到符合要求的输出。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

