我有一个包含姓名,姓氏,生日和一些随机变量的数据框。让我们说它看起来像这样:
BIRTH NAME SURNAME random_value institution
1 1 Luke Skywalker 1 1111
2 1 Luke Skywalker 2 1111
4 2 Leia Organa 3 1211
5 3 Han Solo 7 1342
7 1 Ben Solo 1 1342
8 5 Lando Calrissian 3 1111
9 3 Han Solo 4 1111
10 3 Ham Solo 4 1342
11 1 Luke Wkywalker 9 1111
如果根据BIRTH
,NAME
和SURNAME
输入名称或姓氏的拼写错误,我怎么能弄明白,然后用正确的名字或姓氏替换拼写错误?
例如,我们看到,Han Solo
上有两个带有生日的3
,然后有一个Ham Solo
具有相同的生日。我希望此算法要做的是确定Ham
错误并将其替换为Han
。
如果有两种不同的拼写具有相同的出现次数(对于相同的BIRTH
),那么选择哪一种并不重要,只要所有NAME
或此群组的SURNAME
是相同的(因此始终为Ham
或Han
但不会为同一BIRTH
混用。
所以最终的结果就是:
BIRTH NAME SURNAME random_value institution
1 1 Luke Skywalker 1 1111
2 1 Luke Skywalker 2 1111
4 2 Leia Organa 3 1211
5 3 Han Solo 7 1342
7 1 Ben Solo 1 1342
8 5 Lando Calrissian 3 1111
9 3 Han Solo 4 1111
10 3 Han Solo 4 1342
11 1 Luke Skywalker 9 1111
有没有自动化的方法呢?我的数据集很大(> 3千万行),无法手动检查。
我想我们会查找同一个出生的所有姓名和姓氏,然后查看是否有一些奇异的离群值只有一个字母不同或字母的顺序被切换(Luke
vs Lkue
)。当我们找到这样的异常值时,我们会替换它。
我已在R
论坛(How to find a typo in a data frame and replace it)中提出此问题,并得到了回复。我试图直接实现该方法(由于时间复杂性,它失败了)。然后我修改它并在较小的子数据帧上使用它(按BIRTH
分组)。但即便如此,我在R
估计需要超过37个小时且这个数字正在攀升的过程中停止了这个过程。
在python
中有更快的方法吗?如果你能给我任何建议,我将非常感激。
编辑:正如评论中指出的那样,有两个名字相似的人(Jon / John Smit(h))将在同一天出生。在这种情况下,我们要么看机构专栏(每个人应该(但数据集的实际情况可能有点不同),一个机构编号出现8-9次,另一个出现3-4次)。此外,不止一个人共享相同的机构编号。
但由于institution
可能存在错误数据,我们还可以使用以下推理:
如果同一个生日的相同全名出现两次以上,我们可以得出结论,它实际上是一个新人,而不是一个错字(因为同一个人的两个(最多13个)相同的拼写错误不太可能),并且离开它的名字就像它一样。
答案 0 :(得分:0)
首先,我将出生时的名字分组,然后列出产生的姓氏。所以我会得到
['Fkywalker', 'Skywalker', 'Skywalker']
之后我找出了出现次数最多的名字(天行者)并将其他名称与此名称进行比较。要查找拼写错误,我会计算Levenshtein-distance。 当距离低于3时,我认为这是一个拼写错误,并更新这样的字典:
{'wrong_name' : 'right_name'}
然后我用名字做同样的程序。
然后你有两个替换词,你可以简单地替换错误的值。
import pandas as pd
import distance
from collections import Counter
dict_SURNAME = dict()
dict_NAME = dict()
def dist(str1, str2):
return distance.levenshtein(str1, str2)
def find_name(namelist, todict):
for names in namelist:
namesorted = Counter(names).most_common()
for name in namesorted[1:]:
if dist(namesorted[0][0], name[0]) < 3:
todict.update({name[0]: namesorted[0][0]})
dfsurname = df1.groupby(['BIRTH', 'NAME']).SURNAME.apply(list).reset_index()
find_name(dfsurname.SURNAME.tolist(), dict_SURNAME)
dfname = df1.groupby(['BIRTH', 'SURNAME']).NAME.apply(list).reset_index()
find_name(dfname.NAME.tolist(), dict_NAME)
print(dict_SURNAME)
print(dict_NAME)
df2 = df1.replace({'NAME': dict_NAME, 'SURNAME': dict_SURNAME})
print(df2)
答案 1 :(得分:0)
pandas-dedupe库可以完全满足您的需求。
它使您有机会查找包含某些错字的重复行并将其规范化。
pip install pandas-dedupe
这是一个简短的代码示例
import pandas as pd
import pandas_dedupe
# Data
df = pd.DataFrame({'city':
['Seattle', 'Saettle', 'Seatle', 'Seattle',
'New york', ' New York', 'NewYork',
'London', 'london', 'L ondon',
'Milan', 'Milan', 'Milan', 'Milano',
'Paris', 'paris', 'Paris', 'Paris'],
'country' :
['USA', 'USA', 'USA', 'USA',
'USA', 'USA', 'USA',
'UK', 'UK', 'UK',
'ITA', 'ITA', 'ITA', 'ITA',
'FRA', 'FRA', 'FRA', 'FRA']
})
# Deduplication and canonicalization
dd_df = pandas_dedupe.dedupe_dataframe(
df, # Dataframe to deduplicate
field_properties=['city', 'country'], # List of fields to base deduplication on
canonicalize=['city'], # List of fields to canonicalize (optional)
sample_size=0.8, # Size of sample of records to be labelled
)
在此示例中,您基于行city
和country
中的值对行进行重复数据删除,并规范化了变量city
的值。
以下是其工作原理的简短说明:
pandas-dedupe
将要求您将记录样本标记为不同或重复。标记后,重复数据删除将找出两个或两个以上记录重复且重复数据删除并为您规范化的可能性。
注意:重复数据删除选择的规范名称是每个群集中最常见的名称。