R中判断数据框列值是否落在另一数据框区间且Chr匹配
报错原因
你当前使用的逐行对比逻辑要求两个对比的向量长度相等或短向量为长向量的整数倍,df1共5行、df2共3行,完全不满足该要求,因此触发longer object length is not a multiple of shorter object length报错。同时该逻辑本身不符合需求:你需要对df1的每一行遍历所有df2行查找匹配条目,而非两个不等长表逐行对应匹配。
解决方案
方案1:使用fuzzyjoin实现区间连接(代码最简洁)
该方案专门针对区间匹配场景,逻辑直观易维护:
# 安装加载依赖包 install.packages("fuzzyjoin") library(fuzzyjoin) library(dplyr) # 匹配逻辑实现 result <- df1 %>% # 左连接匹配规则:Chr相等、df1的Start落在df2的[Start, End]区间内 fuzzy_left_join(df2, by = c("Chr" = "Chr", "Start" = "Start", "Start" = "End"), match_fun = list(`==`, `>=`, `<=`)) %>% # 按规则生成新列 mutate(no_coverage_in = case_when( !is.na(sample_id.y) ~ sample_id.y, !is.na(Chr.y) ~ "YES", TRUE ~ NA_character_ )) %>% # 保留原始df1列和新增结果列 select(all_of(colnames(df1)), no_coverage_in)
方案2:纯tidyverse实现(无需安装额外扩展包)
如果你不想新增依赖,可以用dplyr+purrr逐行遍历匹配:
library(dplyr) library(purrr) result <- df1 %>% mutate(no_coverage_in = map_chr(seq_len(nrow(.)), function(i){ cur_chr <- Chr[i] cur_start <- Start[i] # 查找df2中符合匹配规则的行 match_rows <- df2[df2$Chr == cur_chr & df2$Start <= cur_start & df2$End >= cur_start, ] # 按规则返回结果 if(nrow(match_rows) >= 1){ return(ifelse(!is.na(match_rows$sample_id[1]), match_rows$sample_id[1], "YES")) } else { return(NA_character_) } }))
结果说明
针对你提供的示例数据,运行后得到的no_coverage_in列结果为:"ss1", "ss1", NA, "ss1", NA,完全符合需求。如果存在多个匹配项,上述代码默认取第一个匹配到的df2行的sample_id,如需合并多个匹配的sample_id,可将返回值修改为paste(na.omit(match_rows$sample_id), collapse = ",")。
内容的提问来源于stack exchange,提问作者zw_nz
相关产品推荐
相关产品推荐

