I am working in R

我的数据中有500,000行,但这里使用的是一个小示例.

我有一些学校工作人员的数据.有些人在一所学校工作,有些人在两所学校工作,有些人在三所学校工作,等等.

学校并不总是记录个人的名字.一所学校记录为威尔,另一所学校记录为威廉.

我还有一个假设:对于一个在不止一所学校工作的人来说,他们的第二个名字和出生日期总是在每一所学校被记录下来.

基于他们名字的相似性,我想要一种方法来识别可能是同一个人的人,然后给他们分配一个ID.

虽然格雷格和格里芬的前两个字母相同,但他们很可能不是同一个人,这两个词之间会有某种隔阂.

sample data:

data_current <- data.frame(first_name = c("will", "william", "william", "laura", "jessica", "jessicalouise", "james", "greg", "griffin"), 
                           last_name = c("smith", "smith", "smith", "maxwell", "maxwell", "maxwell", "lead", "jones", "jones"),
                           date_of_birth = c("2000-01-02","2000-01-02", "2000-01-02", "2007-01-02","2007-01-02","2007-01-02","1999-01-02","2004-01-02","2004-01-02"), 
                           school_id = c(1, 2, 3, 4, 5, 6, 7, 8, 9))
first_name second_name date_of_birth school_id
will smith 2000-01-02 1
william smith 2000-01-02 2
william smith 2000-01-02 3
laura maxwell 2007-01-02 4
jessica maxwell 2007-01-02 5
jessicalouise maxwell 2007-01-02 6
james lead 1999-01-02 7
greg jones 2004-01-02 8
griffin jones 2004-01-02 9

desired data:

前三个人很可能是同一个人,因此分配了相同的Person_id,依此类推……

data_desired <- data.frame(first_name = c("will", "william", "william", "laura", "jessica", "jessicalouise", "james", "greg", "griffin"), 
                           last_name = c("smith", "smith", "smith", "maxwell", "maxwell", "maxwell", "lead", "jones", "jones"),
                           date_of_birth = c("2000-01-02","2000-01-02", "2000-01-02", "2007-01-02","2007-01-02","2007-01-02","1999-01-02","2004-01-02","2004-01-02"), 
                           school_id = c(1, 2, 3, 4, 5, 6, 7, 8, 9),
                           person_id = c(1, 1, 1, 2, 3, 3, 4, 5, 6))
first_name second_name date_of_birth school_id person_id
will smith 2000-01-02 1 1
william smith 2000-01-02 2 1
william smith 2000-01-02 3 1
laura maxwell 2007-01-02 4 2
jessica maxwell 2007-01-02 5 3
jessicalouise maxwell 2007-01-02 6 3
james lead 1999-01-02 7 4
greg jones 2004-01-02 8 5
griffin jones 2004-01-02 9 6

有没有人有解决这个问题的建议?

推荐答案

这里有一种使用字符串相似性的可能性.它在您的示例中运行得很好,因为您的数据完全分离.然而,超过500K的行,您可能会遇到一些问题,但它可以让您开始:

library(stringdist)
library(dplyr)
library(purrr)

group_first <- function(dat, cutoff = 0.5) {
  if (n_distinct(dat) == 1) return(1)

  M <- stringsimmatrix(dat$first_name, dat$first_name, method = "cosine", q = 2)
  l <- unique(lapply(seq_len(nrow(M)), \(x) dat$first_name[M[x, ] > cutoff]))
  
  person_id <- map(dat$first_name, ~ which(grepl(.x, l, fixed = T))) |>
    modify_if(~ length(.x) > 1, ~ 0)
  
  return(unlist(person_id))
}

data_current |>
  mutate(person_id = group_first(pick(everything())), .by = c(date_of_birth, last_name)) |>
  # review output before running next mutate
  mutate(person_id = cur_group_id(), .by = c(date_of_birth, last_name, person_id))

Output

     first_name last_name date_of_birth school_id person_id
1          will     smith    2000-01-02         1         1
2       william     smith    2000-01-02         2         1
3       william     smith    2000-01-02         3         1
4         laura   maxwell    2007-01-02         4         2
5       jessica   maxwell    2007-01-02         5         3
6 jessicalouise   maxwell    2007-01-02         6         3
7         james      lead    1999-01-02         7         4
8          greg     jones    2004-01-02         8         5
9       griffin     jones    2004-01-02         9         6

How it works

  1. 取每个出生组的姓氏和日期,并计算二元字符余弦相似度分数.如果该相似性分数大于0.5(默认情况下),则将名字分组在一起.
  2. 一个名字可能在多个名字分组中,如果是这样,则返回零,并且这些特殊情况将需要进一步审查.例如,"jess"可以与"jessica"和"jesse"匹配,但"jesse"不一定与"jessica"匹配.此时,ID在姓氏和出生日期内是唯一的,但不是全部.
  3. 在步骤2中判断之后(这将需要使用更精细的算法或手动完成),然后重新计算ID,以便它们在不同的人中是不同的.

正如 comments 中提到的,对于具有相似的二元语法但又不相同的名字来说,这可能会很棘手.这些情况将很难区分.此外,由于这只是一个词汇比较,它可能不适用于缩写名称.例如,"Bob"是"Robert"的缩写,"Dick"是"Richard"的缩写.

您还可以考虑使用其他字符串相似性度量.例如,您可以指定Jaro-Winkler相似度(method = 'jw')和权重(p = 0.10).这将使start个名字的权重相同("Will"与"William"),从而导致更高的相似性分数和潜在的分离.

R相关问答推荐

格点中指数、双曲和反双曲模型曲线的正确绘制

传递ggplot2的变量作为函数参数—没有映射级别以正确填充美学

如何提取所有完美匹配的10个核苷酸在一个成对的匹配与生物字符串在R?>

如何通过判断数据框的一列来压缩另一列?

使用rvest从多个页面抓取时避免404错误

如何指定我的函数应该查找哪个引用表?

R中1到n_1,2到n_2,…,n到n_n的所有组合都是列表中的向量?

有没有办法使用ggText,<;Sub>;&;<;sup>;将上标和下标添加到同一元素?

QY数据的处理:如何定义QY因素的水平

R -使用矩阵reshape 列表

使用不同的定性属性定制主成分分析中点的 colored颜色 和形状

在R中,如何从一系列具有索引名的变量快速创建数据帧?

ggplot R:X,Y,Z使用固定/等距的X,Y坐标绘制六边形热图

将列表中的字符串粘贴到R中for循环内的dplyr筛选器中

从线的交点创建面

是否有可能从边界中找到一个点值?

按两个因素将观测值分组后计算单独的百分比

如何使用包metaviz更改标签的小数位数?

生存时间序列的逻辑检验

将字符变量出现次数不相等的字符框整形为pivot_wider,而不删除重复名称或嵌套字符变量