【问题标题】:Using RecordLinkage to Match Unequal Names Columns in Two Dataframes Before Joining with Dplyr在加入 Dplyr 之前,使用 RecordLinkage 匹配两个数据框中的不等名称列
【发布时间】:2016-06-13 02:51:03
【问题描述】:

以下是我想使用 Dplyr 按名字和姓氏加入的两个数据框。

full_join(Names1,Names2,by=c("FirstNames",LastNames")

但是,某些名称的拼写和格式存在差异。我想使用 RecordLinkage (或 adist)来匹配相似的名称,然后覆盖名称,以便它们在加入之前在两个数据帧中匹配。 (我也意识到“FirstNames”和“LastNames”列在两个数据框中都有不同的标题......所以必须更改。)

FirstNames<-c("Chris","Shintaro","Doug","Elsa","Bubbles","Kelly","Christine")
LastNames<-c("MacDougall","Yamazaki","Shapiro","Elizabeth Ray","Murphy","Anderson","Yamaguchi")
Pets<-c("Cat","Dog","Cat","Dog","Cat","Snake","Eagle")
Names1<-data.frame(FirstNames,LastNames,Pets)

FirstNames2<-c("Chris","Doug","Shintaro","Bubbles","Elsa")
LastNames2<-c("MacDougal","Shapiro","Yamazaku","Murphy","Elizabeth")
Dwelling<-c("House","House","Apartment","Condo","House")
Names2<-data.frame(FirstNames2,LastNames2,Dwelling)

以下是我在 RecordLinkage 包中使用的一些步骤,但我遇到了“错误:所有 select() 输入必须解析为整数列位置。”这是因为数据框的行数不同吗?

Results <- compare.linkage(Names1, Names2, blockfld = 1, strcmp = T, exclude = 3)
PairsSelect <- 
Results$pairs %>% 
select(firstNameSim = FirstNames, lastNameSim = LastNames)

我想继续使用代码将名称列与上面的 PairsSelect 数据连接起来,以便我可以在名字和姓氏列中找到匹配项,然后覆盖两个数据框,使每个数据框具有相同的名称拼写和格式在加入之前。我只是不确定如何最好地处理一个数据帧(Names1)比另一个数据帧(Names2)包含更多行的事实。

任何关于如何实现这一目标的指导将不胜感激!

【问题讨论】:

  • 姓氏不完全匹配并且Results$pairs$LastNames 包含非整数值,这会导致错误。看来您真正想做的是Results$pairs[, c("id1", "id2")] 或使用dplyrResults$pairs %&gt;% select(firstNameSim = id1, lastNameSim = id2)
  • 谢谢。在示例中,“Results$Pairs”是列表的一部分,但如何使其成为单独的数据框,以便将其加入 Names1 和 Names2?
  • 我想按名字和姓氏加入表格...所以必须更改列名。
  • 表只加入完全匹配的键值。首要任务是比较和对齐您的全名以完美匹配从一个表到另一个表,以便您可以将它们作为加入表的真正关键吗?此外,由于个人的全名实际上是表中唯一身份的最原子单位,将它们连接起来并将全名与全名对齐是否最有帮助?
  • 我想最好将名字和姓氏连接起来作为加入表格的真正关键。我想最好加入两列而不是四列。

标签: r string dplyr


【解决方案1】:

我已将键与进入“compare.linkage”函数的数据分开,这与数据库世界观相比有点狡猾,但只要你在加入之前不重新排列相对于 df 的名称compare.linkage() 流回来的一切都将保持正确。

library(dplyr)
library(RecordLinkage)

FirstNames<-c("Chris","Shintaro","Doug","Elsa","Bubbles","Kelly","Christine","Thomas","George")
LastNames<-c("MacDougall","Yamazaki","Shapiro","Elizabeth Ray","Murphy","Anderson","Yamaguchi","DelTorre","Fibonacci")
Pets<-c("Cat","Dog","Cat","Dog","Cat","Snake","Eagle","Shark","Parrot")
Names1<-data.frame(FirstNames,LastNames,Pets,FullNames = paste0(FirstNames, " ", LastNames))

FirstNames2<-c("Chris","Doug","Shintaro","Bubbles","Elsa","George")
LastNames2<-c("MacDougal","Shapiro","Yamazaku","Murphy","Elizabeth","Fibos")
Dwelling<-c("House","House","Apartment","Condo","House","Camper")
Names2<-data.frame(FirstNames2,LastNames2,Dwelling,FullNames2 = paste0(FirstNames2, " ", LastNames2))

df1 <- mutate(id1 = row_number(), Names1)
df2 <- mutate(id2 = row_number(), Names2)

Results <- compare.linkage(Names1, Names2, strcmp = T, exclude = c(1:3))

BestResults <- 
    Results$pairs %>% 
    arrange(desc(FullNames))

BestResultsJoined<- 
    full_join(BestResults,df1,by="id1")%>% 
    full_join(df2,by="id2")%>% 
    select(FullNamesSim=FullNames.x,FullNames1=FullNames.y,FullNames2,id1,id2)
BestResultsJoined

这将为您提供最接近匹配到最不接近匹配的排序列表。看起来您不想考虑任何小于 0.95 的相似度(按 Jaro-Winkler 距离)。

【讨论】:

  • 再次感谢您。当我尝试将上述代码应用于我的实际数据时,我又有点卡住了。在我运行“compare.linkage”之后,$pairs 部分不会显示我的所有数据。我的数据框的“全名”列之一有 116 个值,另一个数据框有 107 个值。我向两者都添加了唯一的 id,然后使用 Dplyr“选择”仅提取数据帧的 id 列和全名列,因为我认为 RecordLinkage 的“排除”选项不起作用,因为两个数据帧都有完全不同的列类型。几乎所有条目都应该匹配...
  • 在两个全名列之间,只有大约 21 个条目拼写错误,或者存在于一个数据帧中但不存在于另一个数据帧中。然而,compare.linkage 的结果只显示了 35 个结果,只有两个编码为“1”......关于发生了什么的任何想法?我决心让这个过程发挥作用,哈哈。
  • 为了清楚起见,compare.linkage 总共只显示 35 个结果......当应该接近 100 个时,大多数匹配为完美的“1”......
  • 您是否将参数更改为 exclude=1 ?那应该比较除 id 之外的所有内容,不是吗?
  • also: 上述代码中的 exclude 参数存在错误。它应该是exclude=c(1,4)。在 Names 表中添加 id 后,我忽略了更新函数。 [不影响最终输出,但 results$pairs df 将宠物与住宅进行比较。] 事实上,如果您想从比较中排除除全名之外的所有列,您只需更新此示例中的代码以读取 @987654326 @。好主意:-D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-09-26
  • 2019-06-04
  • 1970-01-01
  • 2022-01-23
  • 2017-10-18
  • 2020-05-23
  • 1970-01-01
相关资源
最近更新 更多