r - 单个列表中的近似字符串匹配 - r

标签 r string-matching agrep

我在一个数据框中有一个列表,其中包含一个长列表中的数千个名称。许多名称之间存在细微差异,这使它们略有不同。我想找到一种方法来匹配这些名称。例如:

names <- c('jon smith','jon, smith','Jon Smith','jon smith et al','bob seger','bob, seger','bobby seger','bob seger jr.')

我查看了 stringdist 函数中的 amatch 以及 agrep,但这些都需要 master list of names用于匹配另一个名称列表。就我而言,我没有这样的主列表,所以我想通过识别具有高度相似模式的名称来从数据中创建一个,这样我就可以查看它们并确定它们是否是同一个人(在许多他们是)。我想要一个新列中的输出,它可以帮助我知道这些是可能的匹配项,并且可能是基于 Levenshtein 距离或其他东西的某种相似性得分。也许是这样的:

            names   match      SimilarityScore
1       jon smith     a               9
2      jon, smith     a               8
3       Jon Smith     a               9
4 jon smith et al     a               5
5       bob seger     b               9
6      bob, seger     b               8
7     bobby seger     b               7
8   bob seger jr.     b               5

这样的事情可能吗?

最佳答案

根据找到的帖子 here我发现分层文本聚类可以满足我的需求。

  names <- c('jon smith','jon, smith','Jon Smith','jon smith et al','bob seger','bob, seger','bobby seger','bob seger jr.','jake','jakey','jack','jakeyfied')

# Levenshtein Distance
e  <- adist(names)
rownames(e) <- names
hc <- hclust(as.dist(e))
plot(hc)
rect.hclust(hc,k=3) #the k value provides the number of clusters
df <- data.frame(names,cutree(hc,k=3))

如果您选择正确数量的集群(在本例中为三个),输出看起来非常好:

                       names             cutree.hc..k...3.
jon smith             jon smith                 1
jon, smith           jon, smith                 1
Jon Smith             Jon Smith                 1
jon smith et al jon smith et al                 1
bob seger             bob seger                 2
bob, seger           bob, seger                 2
bobby seger         bobby seger                 2
bob seger jr.     bob seger jr.                 2
jake                       jake                 3
jakey                     jakey                 3
jack                       jack                 3
jakeyfied             jakeyfied                 3

但是,名称通常比这更复杂,在添加了一些更难的名称后,我发现默认的 adist 选项并没有提供最佳的聚类:

names <- c('jon smith','jon, smith','Jon Smith','jon smith et al','bob seger','bob, seger','bobby seger','bob seger jr.','jake','jakey','jack','jakeyfied','1234 ranch','5678 ranch','9983','7777')

d  <- adist(names)
rownames(d) <- names
hc <- hclust(as.dist(d))
plot(hc)
rect.hclust(hc,k=6)

Cluster2

我可以通过将替换值的成本增加到 2 并将插入和删除成本保持在 1 并忽略大小写来改进这一点。这有助于最大限度地减少对完全不同的四个字符数字字符串的错误分组,我不想分组:

d  <- adist(names,ignore.case=TRUE, costs=c(i=1,d=1,s=2)) #i=insertion, d=deletion s=substitution
rownames(d) <- names
hc <- hclust(as.dist(d))
plot(hc)
rect.hclust(hc,k=6

enter image description here

我通过使用 grep 包中的 gsub 工具删除诸如“牧场”和“等”之类的常用术语并增加一个集群:

names<-gsub("ranch","",names)
names<-gsub("et al","",names)
d  <- adist(names,ignore.case=TRUE, costs=c(i=1,d=1,s=2))
rownames(d) <- names
hc <- hclust(as.dist(d))
plot(hc)
rect.hclust(hc,k=7)

enter image description here

虽然有一些方法可以让数据整理出最好的簇数,而不是手动尝试挑选数字,但我发现使用反复试验最容易,虽然有信息here about that approach .

关于r - 单个列表中的近似字符串匹配 - r,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27468664/

相关文章:

r - na.locf 但不要做尾随 NA

r - 如何从数据集中选择随机列

从列表中删除子列表

r - 如何使用 agrep 获得模糊字符串匹配的精确公共(public) "max.distance"值?

c++ - 有效地检查一个字符串是否是(大约包含在)另一个字符串的近似子字符串,直到给定的错误阈值?

R data.table : Difference between nested regressions results

javascript - IE与字符串匹配

r - 删除数据框中引用另一个 (R) 中不存在的 ID 的行?

iphone - 字符串匹配 objective-c

r - R中的部分字符串匹配并修剪字符