如何在数据框中找到拼写错误并替换它

Rav*_*rip 1 r dataframe data-cleaning

我有一个包含姓名,姓氏,生日和一些随机变量的数据框.让我们说它看起来像这样:

    BIRTH  NAME    SURNAME random_value
 1      1  Luke  Skywalker            1
 2      1  Luke  Skywalker            2
 4      2  Leia     Organa            3
 5      3   Han       Solo            7
 7      1   Ben       Solo            1
 8      5 Lando Calrissian            3
 9      3   Han       Solo            4
 10     3   Ham       Solo            4
 11     1  Luke  Wkywalker            9
Run Code Online (Sandbox Code Playgroud)

我怎样才能弄清楚,如果在名字或姓氏拼写错误的基础上BIRTH,NAMESURNAME,然后请用正确的名字或姓氏错字?

例如,我们看到,有两个Han Solos带有生日3,然后有一个Ham Solo带有相同的生日.我希望这个算法要做的是弄清楚Ham是错的并替换它Han.

如果有两种不同的拼写具有相同的出现次数(相同BIRTH),那么选择哪一种并不重要,只要所有NAMESURNAME该组的所有或相同(因此总是HamHan不混合)同样BIRTH).

所以最终的结果是:

BIRTH   NAME          SURNAME random_value
    1      1  Luke  Skywalker            1
    2      1  Luke  Skywalker            2
    4      2  Leia     Organa            3
    5      3   Han       Solo            7
    7      1   Ben       Solo            1
    8      5 Lando Calrissian            3
    11     3   Han       Solo            4
    12     3   Han       Solo            4
    13     1  Luke  Skywalker            9
Run Code Online (Sandbox Code Playgroud)

有没有自动化的方法来做到这一点?我的数据集很大(> 3千行),无法手动检查.

我想我们会找出同一个出生的所有名字和姓氏,然后检查,如果有一些奇异的异常值只有一个字母不同或者字母的顺序被切换(Lukevs Lkue).当我们找到这样的异常值时,我们会替换它.

Gor*_*ald 8

这是查找拼写错误的一种方法.首先,定义您在问题中提到的数据框:

my_df<-data.frame(BIRTH = c(1,1,2,3,1,5,3,3,1),
       NAME = c("Luke","Luke","Leia","Han","Ben","Lando","Han","Ham","Luke"),
       SURNAME = c("Skywalker","Skywalker","Organa","Solo","Solo","Calrissian","Solo","Solo","Wkywalker"),
       random_value = c(1,2,3,7,1,3,4,4,9))
Run Code Online (Sandbox Code Playgroud)

其次,创建一个新列,组合您要匹配的所有条目:

my_df$birth_and_names <- do.call(paste, c(my_df[c("BIRTH", "NAME", "SURNAME")], sep = " ")) 
Run Code Online (Sandbox Code Playgroud)

第三,使用包stringdist定义基于字符串距离的距离矩阵:

library(stringdist)
dist.matrix<-stringdistmatrix(my_df$birth_and_names,my_df$birth_and_names,method='jw',p=0.1)
row.names(dist.matrix)<-my_df$birth_and_names
names(dist.matrix)<-my_df$birth_and_names
dist.matrix<-as.dist(dist.matrix)
Run Code Online (Sandbox Code Playgroud)

第四,聚类并将结果显示为树状图.

clusts<-hclust(dist.matrix,method="ward.D2")
plot(clusts)
Run Code Online (Sandbox Code Playgroud)

请参见此处的树状图:

相关名称的树形图

现在,您确切地想要设置参数以自动组合相似的结果当然取决于您,并且取决于问题.假阳性和假阴性之间通常存在权衡取舍.

对于这个例子,在0.2的距离切割似乎是合适的,所以:

my_df$LikelyGroup<-cutree(clusts,h=0.2)
Run Code Online (Sandbox Code Playgroud)

现在my_df$LikelyGroup是标识符列,每个人有一个数字,即使它们拼写错误.

现在命名组,找到每个名称/生日列的模式:

library(dplyr)

Mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}

my_df<-my_df%>%
  group_by(LikelyGroup)%>%
  mutate(Group_Birth=Mode(BIRTH),
         Group_Name=Mode(NAME),
         Group_Surname=Mode(SURNAME))
Run Code Online (Sandbox Code Playgroud)

输出my_df:

 BIRTH|NAME |SURNAME   | random_value| LikelyGroup| Group_Birth|Group_Name |Group_Surname 
------|-----|----------|-------------|------------|------------|-----------|--------------
     1|Luke |Skywalker |            1|           1|           1|Luke       |Skywalker     
     1|Luke |Skywalker |            2|           1|           1|Luke       |Skywalker     
     2|Leia |Organa    |            3|           2|           2|Leia       |Organa        
     3|Han  |Solo      |            7|           3|           3|Han        |Solo          
     1|Ben  |Solo      |            1|           4|           1|Ben        |Solo          
     5|Lando|Calrissian|            3|           5|           5|Lando      |Calrissian    
     3|Han  |Solo      |            4|           3|           3|Han        |Solo          
     3|Ham  |Solo      |            4|           3|           3|Han        |Solo          
     1|Luke |Wkywalker |            9|           1|           1|Luke       |Skywalker     
Run Code Online (Sandbox Code Playgroud)

请参阅https://gist.github.com/gdmcdonald/9135ec8f7e903a0735a0b16d8cb97297