从含非配对样本的数据集中筛选仅含配对样本ID的子集
数据集清洗:保留同时含样本与对照的ID所有行
问题背景
现有非配对样本数据集,部分ID同时包含1条对照(control)行和多条样本(Sample)行,部分ID仅含样本或仅含对照。
示例数据集
ID Sample_Type Species 1 Sample A 1 Sample B 1 Sample C 1 Sample D 2 Sample A 2 Sample B 2 Sample C 2 Sample D 2 Sample E 2 Sample F 2 control NA 3 sample B 3 sample C 3 sample D 3 sample E 3 sample G 3 control B 4 sample A 4 sample B 4 sample C 4 sample G 4 sample J 4 sample K 5 control NA
需求说明
- 保留同时包含样本与对照的ID对应的所有行(如示例中的ID 2、3)
- 排除仅含样本(ID1、4)或仅含对照(ID5)的行
- 处理大型数据集,不随机抽样、不仅保留单行
原尝试代码(存在错误)
data2<- data %>% select(ID, Sample_Type, Species) %>% filter(if (data$Sample_Type = "Control" & "Sample") {SiteID = TRUE})
错误分析
- 未按ID分组判断,逻辑无法覆盖“同一ID下同时存在两种类型”的核心需求
- 比较运算符误用
=而非==,且filter内的if语句写法不符合dplyr语法 - 管道内错误使用
data$引用列名,还出现未定义的SiteID变量
修正后的代码
方法1:dplyr分组筛选(直观易用)
library(dplyr) data2 <- data %>% select(ID, Sample_Type, Species) %>% # 统一类型字段的大小写,避免大小写差异导致漏判 mutate(Sample_Type = toupper(Sample_Type)) %>% group_by(ID) %>% # 筛选出同时包含样本和对照的ID组,保留组内所有行 filter(all(c("SAMPLE", "CONTROL") %in% Sample_Type)) %>% ungroup()
方法2:先提取有效ID再匹配(适合超大型数据集)
library(dplyr) # 先筛选出同时包含两种类型的ID valid_ids <- data %>% mutate(Sample_Type = toupper(Sample_Type)) %>% distinct(ID, Sample_Type) %>% group_by(ID) %>% filter(n() == 2) %>% pull(ID) # 用有效ID匹配原数据集,保留所有对应行 data2 <- data %>% select(ID, Sample_Type, Species) %>% filter(ID %in% valid_ids)
代码说明
toupper(Sample_Type):统一字段大小写,解决示例中Sample/sample、control/Control的大小写不一致问题- 方法1通过分组后判断组内是否同时存在两种类型,直接保留符合条件的所有行,逻辑清晰
- 方法2先提取有效ID列表再筛选,减少大型数据集的分组计算开销,效率更高
内容的提问来源于stack exchange,提问作者mbasista
相关产品推荐
相关产品推荐

