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,NAME和SURNAME,然后请用正确的名字或姓氏错字?
例如,我们看到,有两个Han Solos带有生日3,然后有一个Ham Solo带有相同的生日.我希望这个算法要做的是弄清楚Ham是错的并替换它Han.
如果有两种不同的拼写具有相同的出现次数(相同BIRTH),那么选择哪一种并不重要,只要所有NAME或SURNAME该组的所有或相同(因此总是Ham或Han不混合)同样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).当我们找到这样的异常值时,我们会替换它.
这是查找拼写错误的一种方法.首先,定义您在问题中提到的数据框:
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