首页 > 解决方案 > 用于查找相似名称的 R 函数?

问题描述

我正在使用一个大的名称数据集,并且需要能够按个人分组。可能在数据集中存在看起来不同但属于同一个人的姓名,例如 John Doe 或 John A. Doe,或者 Michael Smith 和 Mike Smith。R有没有办法找到这样的实例并将它们识别为同一个人?

df <- data.frame(
  name = c("John Doe", "John A. Doe", "Jane Smith", "Jane Anderson", "Jane Anderson Lowell",
           "Jane B. Smith", "John Doe", "Jane Smith", "Michael Smith",
"Mike Smith", "A.K. Ross", "Ana Kristina Ross"),
  rating = c(1,2,1,1,2,3,1,4,2,1,3,2)
)

在这里,有多个重复的个体,无论变体是中间名首字母、缩短的名字、加长的名字,还是姓氏改变的人。我一直在尝试找到一个函数,该函数可以给出名称匹配中字符的相似百分比,然后我可以从那里手动检查高百分比的案例以评估它们是否确实是同一个人。我的最终目标是找到每个人的平均评分,我需要按个人排序。

标签: rdplyrtidyrstringr

解决方案


有许多算法可以测量字符串距离。这是使用stringdistpackage的示例数据集的简单方法。正如函数文档所建议的stringdist(),Jaro-Winkler 距离用于查找名称对之间的字符串距离。请注意,我只将名称与相同的前两个字母配对。通过目测,0.15 的字符串距离似乎是定义匹配的合理阈值。

library(tidyverse)
library(stringdist)

get_string_distance <- function(x) {
  if (length(x) == 1) {
    data.frame(name1 = x, name2 = x, string_distance = NA_real_)
  } else {
    x %>% 
      unique() %>% 
      combn(2) %>% 
      t() %>% 
      as.data.frame() %>% 
      setNames(c("name1", "name2")) %>% 
      mutate(string_distance = stringdist(name1, name2, method = "jw"))
  }
}

dat <- df %>% 
  mutate(two_letters = str_sub(name, 1, 2)) %>% 
  nest_by(two_letters) %>% 
  mutate(same_name = list(get_string_distance(data$name))) %>% 
  ungroup()

dat1 <- dat %>% 
  unnest(same_name) %>% 
  filter(string_distance < 0.15) %>% 
  select(name1, name2, string_distance)

dat1

# # A tibble: 4 x 3
#   name1         name2                string_distance
#   <chr>         <chr>                          <dbl>
# 1 Jane Smith    Jane B. Smith                 0.0769
# 2 Jane Anderson Jane Anderson Lowell          0.117 
# 3 John Doe      John A. Doe                   0.0909
# 4 Michael Smith Mike Smith                    0.136 

推荐阅读