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

时间:2013-05-30 13:24:58

标签: r merge 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

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

2 个答案:

答案 0 :(得分:15)

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

> soundex('Clenton') == soundex('Clinton')
[1] TRUE

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

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

> vwr::levenshtein.distance('Clinton', 'Clenton')
Clenton 
  1 

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

答案 1 :(得分: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

我建议设置一个相当高的阈值(可能是0.9)进行自动匹配,然后将记录发送到高阈值以下,但高于次要下限(可能是0.7)到人类评论。你应该玩这些数字,看看哪些对你有用。这些值将决定您的sensitivity/specificity trade-off