R语言:保留各连续数值序列首项,其余重复值替换为NA(求dplyr方案)
问题需求
需要处理数据框中的x列,保留每一段连续非NA数值序列的首个实例,将序列内其余重复数值替换为NA。
示例输入
输入数据集代码:
x = c(1,1,1,NA,NA,NA,3,3,3,NA,NA,1,1,1,NA) data = data.frame(x)
输入数据展示:
x 1 1 2 1 3 1 4 NA 5 NA 6 NA 7 3 8 3 9 3 10 NA 11 NA 12 1 13 1 14 1 15 NA
期望输出
x 1 1 2 NA 3 NA 4 NA 5 NA 6 NA 7 3 8 NA 9 NA 10 NA 11 NA 12 1 13 NA 14 NA 15 NA
dplyr实现方案
可以通过标记连续非NA序列并分组,再在每组内仅保留第一个值的方式实现:
library(dplyr) result <- data %>% # 生成分组ID:每遇到新的非NA段(前一个值为NA或当前是第一行),分组ID累加 mutate(group_id = cumsum(!is.na(x) & (is.na(lag(x)) | row_number() == 1))) %>% # 按分组ID分组 group_by(group_id) %>% # 仅保留每组第一个值,其余替换为NA mutate(x = ifelse(row_number() == 1, x, NA)) %>% # 取消分组并移除临时分组列 ungroup() %>% select(-group_id) print(result)
代码说明
cumsum(!is.na(x) & (is.na(lag(x)) | row_number() == 1)):通过累加判断条件,为每一段连续的非NA值分配唯一的分组ID,确保同一段连续非NA值在同一组。group_by(group_id):基于生成的分组ID对数据分组。ifelse(row_number() == 1, x, NA):在每个分组内,仅保留第一行的原x值,其余行替换为NA。ungroup()和select(-group_id):清理临时分组标识,得到干净的结果数据框。
简洁替代方案(结合data.table)
如果可以引入data.table包,rleid函数能更高效地生成连续序列的分组ID:
library(dplyr) library(data.table) result <- data %>% mutate(group_id = rleid(is.na(x))) %>% group_by(group_id) %>% mutate(x = ifelse(row_number() == 1 & !is.na(x), x, NA)) %>% ungroup() %>% select(-group_id)
内容的提问来源于stack exchange,提问作者Martyna F
相关产品推荐
相关产品推荐

