R语言dataframe按组删除包含子群A坐标区间的B子群对应行
R实现分组区间筛选需求
原始数据
现有结构如下的dataframe:
Groups NAMES start end G1 A 1 50 G1 A 25 45 G1 B 20 51 G1 A 51 49 G2 A 200 400 G2 B 1 1600 G2 A 2000 3000 G2 B 4000 5000
对应dput格式数据:
structure(list(Groups = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("G1", "G2"), class = "factor"), NAMES = structure(c(1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L), .Label = c("A", "B"), class = "factor"), start = c(1L, 25L, 20L, 51L, 200L, 1L, 2000L, 4000L), end = c(50L, 45L, 51L, 49L, 400L, 1600L, 3000L, 5000L)), class = "data.frame", row.names = c(NA, -8L))
需求说明
在每个Groups分组内,若存在任意一条NAMES为A的记录的start和end坐标区间完全落在某条NAMES为B的记录的坐标区间内,则删除该条B记录,所有A记录全部保留,仅保留不存在A区间包含在内的B记录。
期望输出
Groups NAMES start end G1 A 1 50 G1 A 25 45 G1 A 51 49 G2 A 200 400 G2 A 2000 3000 G2 B 4000 5000
实现代码
使用dplyr包实现逻辑如下,兼容区间start大于end的特殊情况:
library(dplyr) # 构造数据 df <- structure(list(Groups = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("G1", "G2"), class = "factor"), NAMES = structure(c(1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L), .Label = c("A", "B"), class = "factor"), start = c(1L, 25L, 20L, 51L, 200L, 1L, 2000L, 4000L), end = c(50L, 45L, 51L, 49L, 400L, 1600L, 3000L, 5000L)), class = "data.frame", row.names = c(NA, -8L)) # 数据处理 result <- df %>% group_by(Groups) %>% mutate(keep = case_when( # 所有A记录直接保留 NAMES == "A" ~ TRUE, NAMES == "B" ~ { # 提取当前组所有A的区间 a_df <- filter(cur_data(), NAMES == "A") # 计算当前B区间的实际上下限 b_low <- min(start, end) b_high <- max(start, end) # 检查是否有任意A的区间完全落在当前B区间内,没有则保留该B记录 !any(pmin(a_df$start, a_df$end) >= b_low & pmax(a_df$start, a_df$end) <= b_high) } )) %>% filter(keep) %>% select(-keep) %>% ungroup() # 查看结果 print(result)
运行结果
# A tibble: 6 × 4 Groups NAMES start end <fct> <fct> <int> <int> 1 G1 A 1 50 2 G1 A 25 45 3 G1 A 51 49 4 G2 A 200 400 5 G2 A 2000 3000 6 G2 B 4000 5000
内容的提问来源于stack exchange,提问作者chippycentra
相关产品推荐
相关产品推荐

