在R中按器官分组,基于多列方向定义的范围筛选重叠行并保留最高分记录
解决方法
要实现你的需求,我们可以分步骤处理:先统一每行的范围起始与结束格式,再按分组识别重叠区间,最后保留每个重叠区间内得分最高的行。
完整代码
library(tidyverse) # 你的原始数据 df <- tibble(organ=c(rep("liver",5), rep("lung",5)), col1=c(1,10,100,40,1000,1,10,100,40,1000), col2=c(15,20,50,80,2000,15,20,50,80,2000), direction=c("+","+","-","+","+","+","+","-","+","+"), score=c(50,100,300,10,300,50,100,300,10,300)) # 核心处理逻辑 result <- df %>% # 第一步:根据direction统一范围的start和end mutate( start = case_when( direction == "+" ~ col1, # "+"方向时,col1为范围起始 direction == "-" ~ col2 # "-"方向时,col2为范围起始 ), end = case_when( direction == "+" ~ col2, # "+"方向时,col2为范围结束 direction == "-" ~ col1 # "-"方向时,col1为范围结束 ) ) %>% group_by(organ) %>% arrange(start) %>% # 按起始位置排序,便于识别重叠关系 # 第二步:标记重叠区间组——当前行起始>上一行结束则为新组 mutate(overlap_group = cumsum(c(TRUE, start[-1] > lag(end)[-1]))) %>% # 第三步:在每个重叠组内保留score最高的行 group_by(organ, overlap_group) %>% filter(score == max(score)) %>% # 清理临时列,还原原始数据结构 select(-start, -end, -overlap_group) %>% ungroup() # 查看最终结果 result
代码解释
- 统一范围格式:通过
case_when根据direction规则,把每行的范围转换成统一的start(起始)和end(结束),消除方向差异,方便后续判断区间重叠。 - 识别重叠组:按
organ分组后,先按start排序,再用cumsum标记重叠区间——如果当前行的起始位置大于上一行的结束位置,就标记为新的重叠组,否则属于同一组。 - 保留最高分行:在每个
organ的每个重叠组里,筛选出score等于该组最高分的行,最后清理临时列得到目标结果。
输出结果
# A tibble: 6 × 5 organ col1 col2 direction score <chr> <dbl> <dbl> <chr> <dbl> 1 liver 10 20 + 100 2 liver 100 50 - 300 3 liver 1000 2000 + 300 4 lung 10 20 + 100 5 lung 100 50 - 300 6 lung 1000 2000 + 300
内容的提问来源于stack exchange,提问作者LDT
相关产品推荐
相关产品推荐

