根据此处找到的帖子,我发现分层文本聚类可以满足我的要求。
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)

我可以通过将替换值的成本增加到 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

gsub
我通过使用包中的工具删除诸如“牧场”和“等”之类的常用术语并将集群数量增加一来进一步微调grep
集群:
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)

尽管有一些方法可以让数据整理出最佳聚类数,而不是手动尝试选择数字,但我发现使用试错法最容易,尽管这里有关于该方法的信息。