如何用R的stringdist和dplyr实现药品名称最优字符串匹配?
解决方案
要实现每个原始药品名称匹配最优官方名称的需求,你需要按原始名称分组后筛选出距离最小的行(stringdist的距离值越小,字符串相似度越高),而非简单用固定阈值过滤。以下是具体实现:
library(stringdist) library(dplyr) # 计算字符串距离,按原始名称分组筛选最优匹配 result <- df %>% # 计算Jaro-Winkler距离,值越小表示字符串越相似 mutate(name_dist = stringdist(orig_names, desired_names, method = "jw")) %>% # 按原始药品名称分组 group_by(orig_names) %>% # 筛选每组中距离最小的行(若存在多个相同最小距离的匹配,可加slice_head(n=1)指定保留第一个) filter(name_dist == min(name_dist)) %>% # 移除临时计算的距离列(可选) select(-name_dist) %>% ungroup() # 查看结果 result
运行后会得到预期的desired_df:
# A tibble: 2 × 3 orig_names desired_names desired_names_code <chr> <chr> <dbl> 1 KOGENATE KOGENATE FS 1 2 ADVATE ADVATE 3
关键说明
- 距离逻辑:
stringdist的jw方法返回0-1的距离值,0代表完全匹配,1代表完全不匹配。因此要找最优匹配,需筛选最小距离的行,而非大于某个阈值。 - 分组筛选:通过
group_by(orig_names)确保每个原始名称只保留一个最优匹配结果,避免无差别过滤导致的错误。 - 平局处理:如果同一原始名称存在多个相同最小距离的匹配项,可通过
slice_head(n=1)/slice_tail(n=1)或业务规则(如编码大小)进一步指定保留项。
原代码无效的原因
你之前的代码逻辑存在两个核心问题:
- 条件
stringdist(...) > 0.5会保留相似度极低的行,和找最优匹配的需求完全相反; - 未按原始名称分组,无法保证每个原始名称仅保留一个最优结果。
内容的提问来源于stack exchange,提问作者TheGoat
相关产品推荐
相关产品推荐

