R语言如何按指定列条件删除数据框中的唯一峰交集行
R语言实现ChIP-seq峰交集数据过滤
问题描述
我有一个包含染色体坐标、峰交集及其他相关信息的数据框,总计127471行、11列,缩略表如下:
| UnionChr | UnionStart | UnionEnd | IntersectChr | IntersectStart | IntersectEnd | IntersectName | Overlap | Genotype |
|---|---|---|---|---|---|---|---|---|
| chr1 | 3657227 | 3658092 | . | -1 | -1 | . | 0 | WT |
| chr1 | 3657227 | 3658092 | chr1 | 3657227 | 3658092 | dko_k27_peak_1 | 865 | DKO |
| chr1 | 3658443 | 3664519 | chr1 | 3658443 | 3662838 | wt_k27_peak_1 | 4395 | WT |
| chr1 | 3658443 | 3664519 | chr1 | 3663340 | 3664519 | wt_k27_peak_2 | 1179 | WT |
| chr1 | 3658443 | 3664519 | chr1 | 3658833 | 3664156 | dko_k27_peak_2 | 5323 | DKO |
| chr1 | 3665636 | 3666032 | chr1 | 3665705 | 3666032 | wt_k27_peak_3 | 327 | WT |
| chr1 | 3665636 | 3666032 | chr1 | 3665636 | 3665919 | dko_k27_peak_3 | 283 | DKO |
| chr1 | 4468858 | 4469245 | chr1 | 4468858 | 4469245 | wt_k27_peak_4 | 387 | WT |
| chr1 | 4468858 | 4469245 | . | -1 | -1 | . | 0 | DKO |
| chr1 | 4472410 | 4473380 | . | -1 | -1 | . | 0 | WT |
| chr1 | 4472410 | 4473380 | chr1 | 4472410 | 4473380 | dko_k27_peak_4 | 970 | DKO |
需要删除所有属于唯一峰交集的行,判定规则为:同一Union区间(UnionChr、UnionStart、UnionEnd三个坐标完全一致的区间)中只要存在Overlap值为0的行,该区间下所有行都需要删除。示例中第1-2行、8-9行、10-11行所属区间均包含Overlap=0的记录,因此全部删除,仅保留第3-7行。
此前尝试过子集筛选、for循环、duplicated()、unique()等方法均未实现目标,因不熟悉Python,仅需单次完成处理,故寻求R语言可行方案。
示例数据构造代码
df <- data.frame(UnionChr=c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1"), UnionStart = c(3657227, 3657227, 3658443, 3658443, 3658443, 3665636, 3665636, 4468858, 4468858, 4472410, 4472410), UnionEnd = c(3658092, 3658092, 3664519, 3664519, 3664519, 3666032, 3666032, 4469245, 4469245, 4473380, 4473380), IntersectChr = c("." , "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", ".", ".", "chr1"), IntersectStart = c(-1, 3657227, 3658443, 3663340, 3658833, 3665705, 3665636, 4468858, -1 , -1, 4472410), IntersectEnd = c( -1, 3658092, 3662838, 3664519, 3664156, 3666032, 3665919, 4469245, -1, -1, 4473380), IntersectName = c(".", "dko_k27_peak_1", "wt_k27_peak_1", "wt_k27_peak_2", "dko_k27_peak_2", "wt_k27_peak_3", "dko_k27_peak_3", "wt_k27_peak_4", ".", ".", "dko_k27_peak_4"), Overlap = c(0, 865, 4395, 1179, 5323, 327, 283, 387, 0, 0, 970), Genotype = c("WT", "DKO", "WT", "WT", "DKO", "WT", "DKO", "WT", "DKO", "WT", "DKO"))
实现方案
不需要写复杂循环,按Union区间分组过滤即可,两种实现方式都可以高效处理12万行数据,运行时间不到1秒:
- 基础R实现(无需安装任何第三方包,适合单次快速处理)
# 为每个Union区间生成唯一分组ID group_id <- paste(df$UnionChr, df$UnionStart, df$UnionEnd, sep = "_") # 提取所有包含Overlap=0的无效区间 invalid_groups <- unique(group_id[df$Overlap == 0]) # 筛选保留非无效区间的所有行 df_filtered <- df[!group_id %in% invalid_groups, ]
- dplyr实现(适合习惯用tidyverse语法的场景)
# 首次使用需先安装包 # install.packages("dplyr") library(dplyr) df_filtered <- df %>% group_by(UnionChr, UnionStart, UnionEnd) %>% filter(!any(Overlap == 0)) %>% ungroup()
运行以上代码后得到的df_filtered和预期结果完全一致,示例数据中会保留第3-7行共5条有效记录。
内容的提问来源于stack exchange,提问作者ispeakcat
相关产品推荐
相关产品推荐

