R语言dplyr实现:基于多条件过滤含NA缺失值的数据行
基于分组列多条件筛选含缺失值行的dplyr实现
问题规则
针对每组包含3个重复测量列的分组数据,按行筛选的保留规则为:若某行在任意一个分组内至少包含2个非缺失值,则保留该行;若所有分组的非缺失值数均小于2,则删除该行。
示例原始数据如下:
a <- data.frame(c('b1', 'b2', 'b3', 'b4'), c(NA, 1.5, 0.5, 1), c(0.4, NA, 0.3, NA), c(0.5, NA, NA,2), c(-0.5, -2.5, -0.2,NA), c(NA, NA, -0.4,NA), c(-0.5, NA, -0.4,NA), stringsAsFactors = FALSE) colnames(a) <- c('id', 'group1_1', 'group1_2', 'group1_3', 'group2_1', 'group2_2', 'group2_3') rownames(a) <- a$id a_subset <- a[, 2:7] a_subset
原始数据输出:
group1_1 group1_2 group1_3 group2_1 group2_2 group2_3 b1 NA 0.4 0.5 -0.5 NA -0.5 b2 1.5 NA NA -2.5 NA NA b3 0.5 0.3 NA -0.2 -0.4 -0.4 b4 1.0 NA 2.0 NA NA NA
预期筛选后删除b2行,保留b1、b3、b4行。
dplyr实现方法
完全可以通过dplyr实现该需求,核心逻辑是按行统计每个分组的非缺失值数量,再按规则判断是否保留。
直观写法(适配小数据量)
用rowwise()按行遍历,搭配c_across()选取对应分组列统计非NA个数,代码可读性强:
library(dplyr) result <- a_subset %>% rowwise() %>% mutate( # 统计group1组非缺失值数量 cnt_g1 = sum(!is.na(c_across(starts_with("group1_")))), # 统计group2组非缺失值数量 cnt_g2 = sum(!is.na(c_across(starts_with("group2_")))) ) %>% # 满足任意一组非NA数>=2即保留 filter(cnt_g1 >= 2 | cnt_g2 >= 2) %>% # 删除统计用的临时列 select(-cnt_g1, -cnt_g2) %>% as.data.frame()
运行后得到的结果和预期输出完全一致:
group1_1 group1_2 group1_3 group2_1 group2_2 group2_3 b1 NA 0.4 0.5 -0.5 NA -0.5 b3 0.5 0.3 NA -0.2 -0.4 -0.4 b4 1.0 NA 2.0 NA NA NA
高性能写法(适配大数据量)
如果数据行数较多,可以用rowSums()做向量化运算,避免逐行遍历的性能损耗:
# 提前匹配分组列名 cols_g1 <- grep("^group1_", colnames(a_subset), value = TRUE) cols_g2 <- grep("^group2_", colnames(a_subset), value = TRUE) result_fast <- a_subset %>% mutate( cnt_g1 = rowSums(!is.na(.[cols_g1])), cnt_g2 = rowSums(!is.na(.[cols_g2])) ) %>% filter(cnt_g1 >=2 | cnt_g2 >=2) %>% select(-cnt_g1, -cnt_g2)
内容的提问来源于stack exchange,提问作者choij
相关产品推荐
相关产品推荐

