在R中匹配文本字符串时处理错误的拼写

gen*_*ser 10 merge r character spelling misspelling

我正在收集调查数据(使用开放数据工具包),我的现场团队,祝福他们的心,有时会对人名的拼写有点创意.所以我有一个"正确的"响应者名称,以及链接到"家庭成员名称"变量的一些记录的年龄变量.有许多不同年龄的家庭成员.我想要受访年龄.

这是一些说明我的问题的虚假数据:

#the respondent
    r = data.frame(name = c("Barack Obama", "George Bush", "Hillary Clinton"))
#a male member
    m = data.frame(name = c("Barack Obama","George", "Wulliam Clenton"), age = c(55,59,70)); m$name=as.character(m$name)
#a female member
    f = data.frame(name = c("Michelle O","Laura Busch", "Hillary Rodham Clinton"), age = c(54,58,69)); f$name=as.character(f$name)
#if the responsent is the the given member, record their age.  if not, NA
    a = cbind(
        ifelse(r$name==m$name,m$age,NA)
        ,ifelse(r$name==f$name,f$age,NA)
        )
    #make a function for plyr that gives me the age of the matched respondent
    f = function(row){
        d = row[is.na(row)==0]
        ifelse(length(d)==0,NA,d)
        }
    require(plyr)
    b = aaply(a,.margins=1,.fun=f)
    data.frame(names=r$name,age=b)
                names age
    1    Barack Obama  55
    2     George Bush  NA
    3 Hillary Clinton  NA

    what.I.would.like = data.frame(names=c("Barack Obama", "George Bush", "Hillary Clinton"),age = c(55,59,70))
    1> what.I.would.like
                names age
    1    Barack Obama  55
    2     George Bush  59
    3 Hillary Clinton  70
Run Code Online (Sandbox Code Playgroud)

在我的真实数据中,我有数百人和多达13个家庭成员.我已经将调查改为分别记录受访年龄,但我有一堆数据需要清理.

Ale*_*iev 16

拼写问题通常通过使用soundex算法的一些变体来处理.RecordLinkage包中有一个R实现.那么你需要比较字符串本身,而不是它们的"语音代码":

> soundex('Clenton') == soundex('Clinton')
[1] TRUE
Run Code Online (Sandbox Code Playgroud)

更新:还有另一种方法可以确定两个单词是否彼此"接近" - 这是一个"距离"是单词之间的某种意义.距离的一个标准度量是将第一个单词转换为第二个单词所需的单字母替换,删除和插入的最小量.它被称为Levenshtein距离.RecordLinkage以及vwr包具有相应的功能:

> levenshteinDist('Clinton', 'Clenton')
[1] 1

> vwr::levenshtein.distance('Clinton', 'Clenton')
Clenton 
  1 
Run Code Online (Sandbox Code Playgroud)

然后,如果距离不超过某个阈值,您可以使用距离并充分考虑单词"close".

  • 两个很好的答案:我将接受声誉较低的人的答案。 (2认同)

Dav*_*arx 12

我建议你使用Jaro-Winkler距离,这是一种字符串相似性度量,用于解决美国人口普查数据中的这个问题.它比levenshtein距离更复杂,专为处理名称而设计.您可以在RecordLinkage包中找到R实现.您需要为两个字符串的相似程度设置一个截止阈值(例如0.8).

install.packages('RecordLinkage','RSQLite')
require(RecordLinkage)

jarowinkler('William Clinton', "Willam Clntn")
# 0.96
jarowinkler('William Clinton', "Wuliam Clinton")
# 0.8462637
jarowinkler('William Clinton', "Hilary Clinton")
# 0.7790765
Run Code Online (Sandbox Code Playgroud)

我建议设置一个相当高的阈值(可能是0.9)进行自动匹配,然后将记录发送到高阈值以下,但高于次要下限(可能是0.7)到人工审查.你应该玩这些数字,看看哪些对你有用.这些值将决定您的敏感性/特异性权衡.

  • 两个很好的答案:我将接受声誉较低的人的答案。 (2认同)