R语言如何仅填充首尾数值相同的NA缺失值区间
R实现:仅填充相同数值之间的NA值
核心实现逻辑:
- 先标记所有非NA值的位置,为每个连续NA段匹配前后相邻的非NA值
- 仅当前后非NA值相等时,用前值填充该段NA
- 所有运算为向量化操作,5万行数据可在毫秒级完成处理
示例基础数据:
Example <- data.frame(col1 = c(1, NA, NA, 4, NA, NA, 6, NA, NA, NA, 6, 8, NA, 2, NA))
方案1:data.table高效方案(推荐大数据量使用)
library(data.table) setDT(Example) # 生成非NA值的分组标记 Example[, grp := rleid(!is.na(col1))] # 构造非NA值的前后段映射表 val_map <- Example[!is.na(col1), .(val = col1, next_grp = grp + 1, prev_grp = grp - 1)] # 按分组判断NA段是否需要填充 Example[is.na(col1), col1 := { prev_val <- val_map[prev_grp == .BY$grp, val] next_val <- val_map[next_grp == .BY$grp, val] if(length(prev_val) == 1 && length(next_val) == 1 && prev_val == next_val) prev_val else NA }, by = grp]
运行后Example$col1输出为:1 NA NA 4 NA NA 6 6 6 6 6 8 NA 2 NA,完全符合需求。
方案2:tidyverse方案
如果习惯使用tidyverse语法,可使用如下实现,效率同样满足5万行数据处理需求:
library(tidyverse) Example <- Example %>% mutate(grp = rleid(!is.na(col1))) %>% # 关联对应NA段的前序、后续非NA值 left_join( filter(., !is.na(col1)) %>% select(prev_grp = grp, prev_val = col1), by = c("grp" = "prev_grp") ) %>% left_join( filter(., !is.na(col1)) %>% select(next_grp = grp, next_val = col1), by = c("grp" = "next_grp") ) %>% # 仅当前后值相等时填充NA mutate(col1 = ifelse(is.na(col1) & prev_val == next_val & !is.na(prev_val) & !is.na(next_val), prev_val, col1)) %>% select(col1)
内容的提问来源于stack exchange,提问作者Daniel Hendrick
相关产品推荐
相关产品推荐

