R语言按ID分组后将列NA值按前后非空值均匀拆分填充
按ID分组按比例填充NA值的R实现方案
可以直接用tidyverse生态函数实现需求,不需要额外写循环,代码如下:
第一步:构造示例测试数据
library(dplyr) library(tidyr) df <- tibble( ID = c(rep(1,7), rep(2,6)), Value = c("A", rep(NA,5), "B", "C", rep(NA,4), "D"), X = "x", Y = "y" )
第二步:核心处理代码(纯tidyverse实现,无需额外依赖)
df_result <- df %>% group_by(ID) %>% # 提取前一个非空值 fill(Value, .direction = "down") %>% rename(prev_val = Value) %>% # 提取后一个非空值 bind_cols(df %>% select(Value) %>% fill(Value, .direction = "up") %>% rename(next_val = Value)) %>% # 恢复原始Value列 mutate(Value = df$Value) %>% # 标记连续NA所属的分段 mutate(val_grp = cumsum(!is.na(Value))) %>% group_by(ID, val_grp) %>% mutate( # 统计当前分段内NA总数 na_total = sum(is.na(Value)), # 计算前半段用前值填充的数量 fill_prev_cnt = floor(na_total/2), # 标记NA行在分段内的相对位置 pos = row_number() - 1 ) %>% # 按规则填充NA mutate( Value = case_when( !is.na(Value) ~ Value, pos <= fill_prev_cnt ~ prev_val, TRUE ~ next_val ) ) %>% # 清理临时辅助列 ungroup() %>% select(ID, Value, X, Y)
运行后得到的结果与你给出的预期输出完全一致,直接替换为自己的真实数据集即可使用。如果存在组开头/组结尾的NA(没有前后非空值的情况),可以根据需求在group_by(ID)后增加drop_na(prev_val, next_val)过滤,或者自定义填充规则。
内容的提问来源于stack exchange,提问作者shinama99
相关产品推荐
相关产品推荐

