R语言如何基于另一数据框的部分文本匹配替换指定列的值
问题描述
这是我在Stack Overflow发布的第一篇帖子,英语并非我的母语,在此提前为可能出现的语法和编程相关错误致歉。
我需要基于另一个数据框中的部分文本值,替换当前数据框某一列的取值。我之前看到过类似需求的解决方案,但现有方案的示例都是所有错误取值和正确值有完整的映射关系,而我只需要通过字符串的部分匹配就可以判断是否要替换取值。
我已经尝试用dplyr的if_else和grepl函数实现需求:当第二个存映射的数据框只有一行时grepl可以正常运行,但新增映射行后就会报错。
我的真实业务数据大概有3万行、33个变量,存映射关系的第二个数据框每个月可能会新增条目,所以我不想用循环来实现这个需求。
模拟数据与测试代码
library(dplyr) df1 <- data.frame(Supplier = c("AAA","CCC","CCE","DDD","EEE","EED","GGG","HHH","III","JJJ"), Value = c(100,200,300,400,200, 100,200,40,150,70)) df2 <- data.frame(Supplier =c("CC","EE","GG"), New_Supplier = c("Red","Blue","Green")) # 示例1:仅当完全匹配时可正常运行: df1$Supplier <- if_else(df1$Supplier %in% df2$Supplier, df2$New_Supplier, df1$Supplier) # 示例2:仅当第二个数据框只有一行时可正常运行: df1$Supplier <- if_else(grepl(df2$Supplier, df1$Supplier), df2$New_Supplier, df1$Supplier)
现有数据
待处理数据df1
Supplier Value 1 AAA 100 2 CCC 200 3 CCE 300 4 DDD 400 5 EEE 200 6 EED 100 7 GGG 200 8 HHH 40 9 III 150 10 JJJ 70
映射关系数据df2
Supplier New_Supplier 1 CC Red 2 EE Blue 3 GG Green
期望输出结果
Supplier Value 1 AAA 100 2 Red 200 3 Red 300 4 DDD 400 5 Blue 200 6 Blue 100 7 Green 200 8 HHH 40 9 III 150 10 JJJ 70
解决方案
之前代码报错的核心原因是grepl()的第一个参数仅支持传入单个正则模式,传入多模式向量时只会识别第一个,还会触发长度不匹配的报错。
你可以用stringr包的str_replace_all()函数实现需求,该方法支持动态新增映射规则,无需调整代码逻辑,处理3万行级别的数据效率远高于循环:
# 未安装stringr可先运行 install.packages("stringr") library(stringr) # 构造匹配替换规则:只要包含对应关键词就替换为指定供应商名 replace_rule <- setNames(df2$New_Supplier, paste0(".*", df2$Supplier, ".*")) df1$Supplier <- str_replace_all(df1$Supplier, replace_rule)
运行上述代码后即可得到你需要的输出结果。
内容的提问来源于stack exchange,提问作者Drahal
相关产品推荐
相关产品推荐

