跨两表正则匹配:百万级数据框分类标记优化需求
高效实现百万级数据框的名称匹配与分类标记
原始数据
df <- data.frame(name = c("name1","name2","name3","name4"), class = c("classA","classA","classB","classC"))
df2 <- data.frame(names = c("name1;name3","name5,name6","name2 name 8","name4"))
需求说明
需要给df2新增两个字段:
class_flag:只要names字段中匹配到df里的任意名称,就标记为Y,否则为Nclasses:把匹配到的所有名称对应的类别用逗号拼接,无匹配则填NA
预期结果如下:
df2 <- data.frame(names = c("name1;name3","name5,name6","name2 name 8","name4"), class_flag = c("Y","N","Y","Y"), classes = c("classA,classB", NA, "classA","classC"))
当前实现的问题
目前仅针对classA做了部分逻辑,整体写法繁琐重复,且面对百万行级别的df2,效率完全跟不上。
高效实现方案
核心思路
- 先把
df转换成名称-类别的映射表,同时生成能匹配所有名称的正则表达式(加单词边界\b确保精确匹配,避免部分匹配) - 批量提取
df2每条记录里匹配到的所有名称 - 基于提取结果快速生成
class_flag和classes字段
代码实现(基础版)
用dplyr+stringr实现,语法简洁且性能不错:
library(dplyr) library(stringr) # 提前构建名称到类别的映射,以及匹配正则 name_class_map <- setNames(df$class, df$name) # 转义名称中的特殊字符,避免正则出错 name_pattern <- str_c("\\b", str_escape(df$name), "\\b", collapse = "|") # 批量处理df2 df2_processed <- df2 %>% mutate( # 提取每条记录里所有匹配的名称 matched_names = str_extract_all(names, name_pattern), # 生成classes字段:去重后拼接类别,无匹配则为NA classes = sapply(matched_names, function(x) { if (length(x) == 0) NA_character_ else str_c(unique(name_class_map[x]), collapse = ",") }), # 生成class_flag字段:有匹配就是Y,否则N class_flag = ifelse(sapply(matched_names, length) > 0, "Y", "N") ) %>% # 移除中间临时字段 select(-matched_names) # 查看最终结果 print(df2_processed)
百万行数据专属优化
如果df2真的有百万行,推荐用stringi包替代stringr,它的正则操作速度更快,替换后的核心代码如下:
library(stringi) library(dplyr) name_class_map <- setNames(df$class, df$name) name_pattern <- stri_c("\\b", stri_escape_unicode(df$name), "\\b", collapse = "|") df2_processed <- df2 %>% mutate( matched_names = stri_extract_all_regex(names, name_pattern), classes = sapply(matched_names, function(x) { if (length(x) == 0) NA_character_ else stri_c(unique(name_class_map[x]), collapse = ",") }), class_flag = ifelse(sapply(matched_names, length) > 0, "Y", "N") ) %>% select(-matched_names)
内容的提问来源于stack exchange,提问作者Ashti
相关产品推荐
相关产品推荐

