我有两个数据格式,都有一个ID和一个包含String的列Name。它们看起来可能是这样的:
Dataframes:
DF-1 DF-2
--------------------- ---------------------
ID Name ID Name
1 56 aaeessa 1 12 H.P paRt 1
2 98 1o7v9sM 2 76 aa3esza
3 175 HP. part 1 3 762 stakoverfl
4 2 stackover 4 2 lo7v9Sm我想计算一个元素和其他元素之间的字符串相似度(Ex: Jaccard,Levenshtein),并选择得分最高的元素。然后匹配这两个I,以便稍后可以加入完整的Dataframes。生成的表应该如下所示:
结果:
Result
-----------------
ID1 ID2
1 56 76
2 98 2
3 175 12
4 2 762这可以很容易地实现使用双for循环,但我正在寻找一个优雅(和更快的方式)来完成这一点,也许兰巴斯的列表理解,或一些熊猫工具。也许是groupby和idxmax的结合,但是我不太可能自己解决这个问题。
编辑: DataFrames具有不同的长度,此函数的目的之一是确定较小数据的哪些元素出现在更大的数据中,并与这些元素匹配,丢弃其余的元素。因此,在结果表中,应该只显示匹配的ID对,或一对ID1 - NaN (假设DF-1的行数比DF-2多)。
发布于 2019-09-20 10:09:26
使用熊猫包装:https://pypi.org/project/pandas-dedupe/
需要使用人工输入来训练分类器,然后它将使用学习的设置来匹配整个数据。
首先使用pip install pandas-dedupe并尝试如下:
import pandas as pd
import pandas_dedupe
df1=pd.DataFrame({'ID':[56,98,175],
'Name':['aaeessa', '1o7v9sM', 'HP. part 1']})
df2=pd.DataFrame({'ID':[12,76,762,2],
'Name':['H.P paRt 1', 'aa3esza', 'stakoverfl ', 'lo7v9Sm']})
#initiate matching
df_final = pandas_dedupe.link_dataframes(df1, df2, ['Name'])
# reset index
df_final = df_final.reset_index(drop=True)
# print result
print(df_final)
ID Name cluster id confidence
0 98 1o7v9sm 0.0 1.000000
1 2 lo7v9sm 0.0 1.000000
2 175 hp. part 1 1.0 0.999999
3 12 h.p part 1 1.0 0.999999
4 56 aaeessa 2.0 0.999967
5 76 aa3esza 2.0 0.999967
6 762 stakoverfl NaN NaN您可以看到匹配的对被分配了一个集群和信任级别。nan是无与伦比的。您现在可以分析这一信息,无论你愿意。例如,也许只考虑信心水平在80%以上的结果。
发布于 2019-09-20 09:28:08
我建议您使用一个名为Python记录链接工具包的库。
导入库后,必须索引要比较的源,如下所示:
indexer = recordlinkage.Index()
#using url as intersection
indexer.block('id')
candidate_links = indexer.index(df_1, df_2)
c = recordlinkage.Compare()假设您希望根据字符串的相似性进行比较,但它们并不完全匹配:
c.string('name', 'name', method='jarowinkler', threshold=0.85)如果你想要一个精确的匹配,你应该使用:
c.exact('name')发布于 2019-09-20 10:12:30
使用链接答案中的fuzzy_wuzzy函数:
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
mrg = fuzzy_merge(df1, df2, 'Name', 'Name', threshold=70)\
.merge(df2, left_on='matches', right_on='Name', suffixes=['1', '2'])\
.filter(like='ID')输出
ID1 ID2
0 56 76
1 98 2
2 175 12
3 2 762https://stackoverflow.com/questions/58025517
复制相似问题