在R中实现球员姓名精准匹配与dplyr数据框无错连接
球员姓名匹配与DataFrame连接解决方案
1. 先做精确匹配(优先覆盖无歧义的情况)
先保留原始姓名列,不要直接替换,新增处理后的字段用于后续匹配:
library(dplyr) # 给两个数据框备份原始姓名 data_1 <- data_1 %>% mutate(original_player = player) %>% # 提取姓氏(最后一个空格后的内容) mutate(last_name = sub('.*\\s', '', player), # 提取名的前缀(空格前的内容,比如W.这种缩写) first_part = sub('\\s.*', '', player)) data_2 <- data_2 %>% mutate(original_player = player) %>% mutate(last_name = sub('.*\\s', '', player), # 提取所有名的部分(拆分后去掉姓氏的部分) first_names = strsplit(player, '\\s') %>% purrr::map_chr(~paste(.[-length(.)], collapse = ' ')))
先匹配完全一致的姓名,把这部分先拎出来:
# 精确匹配原始姓名 matched_exact <- inner_join(data_1, data_2, by = c("player" = "player")) %>% select(original_player.x, original_player.y, Flag) # 移除已匹配的条目,剩下的是需要模糊匹配的 data_1_unmatched <- anti_join(data_1, matched_exact, by = c("original_player" = "original_player.x")) data_2_unmatched <- anti_join(data_2, matched_exact, by = c("original_player" = "original_player.y"))
2. 分层模糊匹配(解决姓氏相同但名不同的歧义)
针对Anguissa这种名部分重叠的情况,同时避免Fofana的错配,我们用「姓氏精确匹配 + 名的部分包含」的逻辑:
library(stringr) # 姓氏必须完全匹配,且一方的名包含另一方的名 matched_partial <- inner_join(data_1_unmatched, data_2_unmatched, by = "last_name") %>% filter(str_detect(first_names.y, fixed(first_part.x)) | str_detect(first_part.x, fixed(first_names.y))) %>% # 防止一个球员对应多个匹配结果,先取第一个(如果有多个,后续手动确认) group_by(original_player.x) %>% slice(1) %>% ungroup() %>% select(original_player.x, original_player.y, Flag) # 更新未匹配列表 data_1_unmatched <- anti_join(data_1_unmatched, matched_partial, by = c("original_player" = "original_player.x")) data_2_unmatched <- anti_join(data_2_unmatched, matched_partial, by = c("original_player" = "original_player.y"))
3. 手动处理剩余未匹配项
总有一些特殊情况(比如拼写差异、罕见姓名),这时候手动匹配是最靠谱的:
# 查看剩下没匹配上的球员 cat("data_1中未匹配的球员:\n") print(data_1_unmatched$original_player) cat("\ndata_2中未匹配的球员:\n") print(data_2_unmatched$original_player) # 手动创建匹配映射,根据实际情况修改 manual_matches <- tibble( original_player.x = c("W. Fofana"), original_player.y = c("对应data_2里的全名") ) # 合并手动匹配结果 matched_manual <- inner_join(data_1_unmatched, manual_matches, by = "original_player.x") %>% inner_join(data_2_unmatched, by = c("original_player.y" = "original_player")) %>% select(original_player.x, original_player.y, Flag)
4. 合并所有匹配结果
把精确匹配、模糊匹配、手动匹配的结果合并起来,就是最终的匹配表:
final_matched <- bind_rows(matched_exact, matched_partial, matched_manual) %>% rename(player_data1 = original_player.x, player_data2 = original_player.y) # 查看最终结果 print(final_matched)
这种方法的好处是:先通过精确匹配减少后续工作量,再用针对性的模糊逻辑解决大部分歧义,最后手动收尾特殊情况,既能保证效率,又能避免错配,比单纯调fuzzyjoin的max_dist更可控。
内容的提问来源于stack exchange,提问作者Mimi Guo
相关产品推荐
相关产品推荐

