如何利用DataFrame列元素字符串批量筛选另一个DataFrame?
R批量筛选DataFrame匹配元素问题
输入数据
set.seed(1) df1 <- data.frame(k1 = "AFD(1);Acf(2);Vgr7(2);" ,k2 = "ABC(7);BHG(46);TFG(675);") df2 <- data.frame(site =c("AFD(1);AFD(2);", "Acf(2);", "TFG(677);", "XX(275);", "ABC(7);", "ABC(9);") ,p1 = rnorm(6, mean = 5, sd = 2) ,p2 = rnorm(6, mean = 6.5, sd = 2))
需求说明
df1的列由多组「字母/数字+括号内数字+分号」格式的元素组成长字符串;df2的site列包含部分来自df1的元素,元素可能单独成串或作为长串的一部分。
需要利用df1的所有列(列名不一定含k)和df2的site列批量筛选df2,最终结果首列为df1的列名,第二列为df2中包含对应df1列元素的site值,其余列保留df2的原有内容。预期结果如下:
> outcome k site p1 p2 1 k1 AFD(1);AFD(2); 4.043700 3.745881 2 k1 Acf(2); 5.835883 5.670011 3 k2 ABC(7); 5.775343 8.700051
遇到的问题
尝试两种方案均失败:
- 方案1:单列生成grep模式但未转义括号,且无法批量处理
- 方案2:拆分元素后丢失分隔符,无法处理部分匹配
解决方案
library(dplyr) library(stringr) library(tidyr) # 处理df1,生成各列对应的匹配正则 df1_processed <- df1 %>% pivot_longer(everything(), names_to = "k", values_to = "raw_elements") %>% mutate( # 拆分元素并过滤空字符串 elements = str_split(raw_elements, ";") %>% map(~ .x[.x != ""]), # 转义括号(正则中()为特殊字符,需转义才能匹配字面量) escaped_elements = map(elements, ~ str_replace_all(.x, fixed("("), "\\(") %>% str_replace_all(fixed(")"), "\\)")), # 合并为单个正则:匹配任意一个元素 match_regex = map_chr(escaped_elements, ~ paste0("(", paste(.x, collapse = "|"), ")")) ) # 批量筛选并合并结果 outcome <- df1_processed %>% rowwise() %>% mutate( # 筛选df2中site包含当前列任意元素的行 matched_data = list(filter(df2, str_detect(site, match_regex))) ) %>% unnest(matched_data) %>% select(k, site, p1, p2) %>% arrange(k) # 输出结果 print(outcome)
代码说明
- 转置df1:用
pivot_longer将df1转为长格式,方便逐列处理; - 处理元素与正则:拆分每列的元素,转义括号避免正则解析错误,再将同列元素合并为「或逻辑」的正则表达式;
- 批量筛选合并:遍历每个df1的列,筛选df2中匹配的行,最后合并所有结果并整理列顺序。
内容的提问来源于stack exchange,提问作者Wera
相关产品推荐
相关产品推荐

