如何在两个列表中识别名称的完全、部分或无匹配并提取行ID
实现两个名称列表的匹配(完全/部分/无匹配)及行ID提取
需求说明
基于dt2中的每个名称,在dt1中完成三类匹配判断:
- 完全匹配:名称完全一致
- 部分匹配:
dt2的名称是dt1中某个名称的子字符串 - 无匹配:上述两种情况均不满足
同时提取dt1中首个匹配行的ID,最终输出格式参考给定的dtout。
输入数据
library(data.table) dt1 <- data.table(nmlist = c('nm1 ln1','nm2 ln2','nm2 ln3','nm4 ln4')) dt2 <- data.table(chknm = c('nm1 ln1','nm2','ln3','nm5 ln5'))
实现代码
# 给dt1添加行ID列 dt1[, index := .I] # 初始化输出表 dtout <- dt2[, .(chknm)] # 第一步:处理完全匹配 dtout[dt1, on = .(chknm = nmlist), `:=`(match = 'exact', index = i.index)] # 第二步:处理未匹配的行(部分匹配/无匹配) unmatched_rows <- dtout[is.na(match)] unmatched_rows[, c('match', 'index') := { # 查找dt1中包含当前chknm的所有行 matched_records <- dt1[grepl(chknm, nmlist)] if (nrow(matched_records) > 0) { .(match = 'partial', index = matched_records$index[1]) } else { .(match = 'nomatch', index = NA_integer_) } }, by = chknm] # 将部分匹配/无匹配的结果更新到输出表 dtout[unmatched_rows, on = .(chknm), `:=`(match = i.match, index = i.index)] # 查看结果 dtout
代码逻辑解释
- 添加行ID:利用
data.table内置的.I获取dt1的行号,后续用于返回匹配位置 - 完全匹配处理:通过
data.table的连接操作(on = .(chknm = nmlist))直接匹配完全一致的名称,标记match = 'exact'并赋值对应行ID - 部分/无匹配处理:对未完成完全匹配的行,按每个名称分组,用
grepl检查dt1中是否存在包含当前名称的记录:- 存在则标记
partial,取首个匹配行的ID - 不存在则标记
nomatch,ID设为NA
- 存在则标记
- 结果合并:将部分匹配/无匹配的结果更新到输出表中,得到最终完整结果
验证结果
运行代码后输出的dtout与预期完全一致:
# chknm match index # 1: nm1 ln1 exact 1 # 2: nm2 partial 2 # 3: ln3 partial 3 # 4: nm5 ln5 nomatch NA
内容的提问来源于stack exchange,提问作者RSA
相关产品推荐
相关产品推荐

