如何在R中基于子串边界匹配实现数据表的左连接?
按子串边界规则实现数据表左连接
需求说明
需要将两个数据表按以下规则做左连接:
- 保留第一个表(
df)的所有数据 - 匹配规则:第二个表(
df2)的key2列子串需完整出现在df的key1列字符串中,且子串前后不能直接跟随字母
示例数据
df <- data.frame(key1 = c("apple pie with custard", "chicken and mushroom pie", "key lime pie", "key limecake")) df2 <- data.frame(key2 = c("key lime", "chicken", "custard"), val = c("dessert", "savoury", "dessert"))
实现方案
这里用dplyr和stringr包实现,核心是通过正则负向前后断言确保子串前后无字母:
library(dplyr) library(stringr) # 定义匹配函数:对每个key1值,找到符合规则的val get_matched_val <- function(target_str) { # 为每个key2构建正则:前后不能是字母,同时转义空格避免匹配问题 regex_patterns <- str_c("(?<![a-zA-Z])", str_replace_all(df2$key2, "\\s", "\\\\s"), "(?![a-zA-Z])") # 找到匹配的key2对应的索引 match_pos <- which(str_detect(target_str, regex_patterns)) # 返回对应val,无匹配则返回NA if (length(match_pos) > 0) df2$val[match_pos] else NA } # 生成结果 final_result <- df %>% mutate(val = sapply(key1, get_matched_val)) # 输出结果 print(final_result)
结果验证
运行后输出与预期一致:
key1 val 1 apple pie with custard dessert 2 chicken and mushroom pie savoury 3 key lime pie dessert 4 key limecake <NA>
其中key limecake不匹配key lime,因为子串后直接跟了字母c,符合规则要求。
补充:Base R 实现
如果不想加载额外包,可以用基础R循环实现:
# 初始化val列 df$val <- NA # 遍历每个key1值,匹配符合规则的key2 for (i in 1:nrow(df)) { current_key1 <- df$key1[i] for (j in 1:nrow(df2)) { # 构建正则规则 pattern <- paste0("(?<![a-zA-Z])", gsub("\\s", "\\\\s", df2$key2[j]), "(?![a-zA-Z])") if (grepl(pattern, current_key1)) { df$val[i] <- df2$val[j] break # 若允许多个匹配,可移除break并处理多值情况 } } } print(df)
内容的提问来源于stack exchange,提问作者Dee G
相关产品推荐
相关产品推荐

