如何解决在 3 个 DataFrame 列中识别略有不同的唯一可识别通用名称的算法
示例 DataFrame
df
有 3 列来标识任何给定的人,即name
、nick_name
、initials
。它们的指定方式可能略有不同,但将三列放在一起看,可以克服这些差异,将给定人员的所有行分开,并使用每个人的单个值对这 3 列进行标准化。
>>> import pandas as pd
>>> df = pd.DataFrame({'ID':range(9),'name':['Theodore','Thomas','Theodore','Christian','Theodore R','Tomas','Cristian'],'nick_name':['Tedy','Tom','Ted','Chris','Tommy','Chris'],'initials':['TR','Tb','TRo','CS','TR','tb','TB','CS']})
>>> df
ID name nick_name initials
0 0 Theodore Tedy TR
1 1 Thomas Tom Tb
2 2 Theodore Ted TRo
3 3 Christian Chris CS
4 4 Theodore Ted TR
5 5 Theodore R Ted TR
6 6 Thomas Tommy tb
7 7 Tomas Tom TB
8 8 Cristian Chris CS
在这种情况下,所需的输出如下:
ID name nick_name initials
0 0 Theodore Ted TR
1 1 Thomas Tom TB
2 2 Theodore Ted TR
3 3 Christian Chris CS
4 4 Theodore Ted TR
5 5 Theodore Ted TR
6 6 Thomas Tom TB
7 7 Thomas Tom TB
8 8 Christian Chris CS
公共值可以是任何值,只要它被标准化为相同的值即可。例如,name
是 Theodore
或 Theodore R
- 两者都可以。
我的实际 DataFrame
大约有 4000 行。有人可以帮助指定最佳算法来做到这一点。
解决方法
您需要使用 Levenshtein 距离来识别相似的字符串。一个很好的 Python 包是 fuzzywuzzy。下面我使用基本的字典方法将相似的行收集在一起,然后用指定的主行覆盖每个块。请注意,这会留下一个包含许多重复行的 CSV,我不知道这是否是您想要的,但如果不是,则很容易删除重复项。
import pandas as pd
from itertools import chain
from fuzzywuzzy import fuzz
def cluster_rows(df):
row_clusters = {}
threshold = 90
name_rows = list(df.iterrows())
for i,nr in name_rows:
name = nr['name']
new_cluster = True
for other in row_clusters.keys():
if fuzz.ratio(name,other) >= threshold:
row_clusters[other].append(nr)
new_cluster = False
if new_cluster:
row_clusters[name] = [nr]
return row_clusters
def normalize_rows(row_clusters):
for name in row_clusters:
master = row_clusters[name][0]
for row in row_clusters[name][1:]:
for key in row.keys():
row[key] = master[key]
return row_clusters
if __name__ == '__main__':
df = pd.read_csv('names.csv')
rc = cluster_rows(df)
normalized = normalize_rows(rc)
pd.DataFrame(chain(*normalized.values())).to_csv('norm-names.csv')
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。