查找不同长度的两个 DataFrame 之间的相似性
Posted
技术标签:
【中文标题】查找不同长度的两个 DataFrame 之间的相似性【英文标题】:Find Similarity between two DataFrames of different lengths 【发布时间】:2016-09-01 20:02:43 【问题描述】:我有两个不同长度的 Pandas 数据框。 DF1 有大约 120 万行(只有 1 列),DF2 有大约 300,000 行(和单列),我正在尝试从两个列表中找到相似的项目。
DF1 有大约 75% 的公司名称和 25% 的人员,而 DF2 则相反,但它们都是字母数字。我想要编写一个函数,该函数将突出显示两个列表中最相似的项目,按分数(或百分比)排名。 例如,
Apple -> Apple Inc. (0.95)
Apple -> Applebees (0.68)
Banana Boat -> Banana Bread (0.25)
到目前为止,我尝试了两种方法,都失败了。
方法一:求两个列表的 Jaccard 系数。
import numpy as np
from sklearn.metrics import jaccard_similarity_score
jaccard_similarity_score(df_1, df_2)
这不起作用,可能是由于两个数据帧的长度不同,我收到此错误:
ValueError: 发现样本数量不一致的数组
方法二::使用序列匹配器
from difflib import SequenceMatcher
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
然后调用数据框:
similar(df_1, df_2)
这会导致错误:
pandas/index.pyx 在 pandas.index.IndexEngine.get_loc (pandas/index.c:3979)()
pandas/index.pyx 在 pandas.index.IndexEngine.get_loc (pandas/index.c:3843)()
pandas/hashtable.pyx 在 pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12265)()
pandas/hashtable.pyx 在 pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12216)()
密钥错误:0
我该如何解决这个问题?
【问题讨论】:
SequenceMatcher
可以匹配字符串,而不是 DataFrames。
您想比较 df1 中的所有 120 万和 df2 中的所有 30 万 您的问题是,您希望最终输出是什么样的?是否要为 df1 的每个元素细化 df2 中最相似的元素?
这是一个类似的答案,但与DataFrame
***.com/questions/36802453/…中的比较
如果您能提供一些示例数据,并描述您想要的输出应该是什么,那将会很有帮助。如果您真的想为两个 DataFrame 中的 每一 对行计算相似度分数,那么您需要生成一个 (300000, 1200000)
数组。假设它包含 64 位浮点数,这个数组将占用大约 2.9TB 的 RAM!我猜您实际上对寻找最近的邻居感兴趣,在这种情况下,您应该查看sklearn.neighbors
,尤其是BallTree
。
DF1 的样本数据:Apple Texas Homes LLC Microsoft Microsoft Ireland Research Google LLC Google Auto LLC John Smith Jane Doe DF2:John Smith Jack Smith Jane Smith Apple Apple Inc Applebees Inc John Johnson Johnson & Johnson 我想要的输出如原始问题中所述 - 相似度得分,以及具有最高匹配度的实体,按降序排列。
【参考方案1】:
解决方案
我必须安装distance
模块,因为它比在这种情况下弄清楚如何使用jaccard_similarity_score
更快。我无法通过该函数重新创建您的号码。
安装distance
pip install distance
使用distance
import distance
jd = lambda x, y: 1 - distance.jaccard(x, y)
df_1.head().iloc[:, 0].apply(lambda x: df_2.head().iloc[:, 0].apply(lambda y: jd(x, y)))
head()
为您提供保护。我很确定删除它们会炸毁您的计算机,因为它会产生 1.2M X 0.3M 矩阵。
试试这个。我不太确定你到底想要什么。我们可以根据您的清晰度进行调整。
【讨论】:
谢谢,我试过你的解决方案,这是我得到的输出。 link鉴于我的数据集只是两个一维列,我不确定如何解释这个结果 - 有什么想法吗? 每个单元格是第一个数据集中第 i 个元素与第二个数据集中第 j 个元素之间的距离。如果您只想要为相同位置的那些元素计算距离,即距离(数据集 1[0],数据集 2[0]),那就更容易了。我会添加一个答案。【参考方案2】:或者为了比较限制在相同元素位置的项目。
import distance
jd = lambda x, y: 1 - distance.jaccard(x, y)
test_df = pd.concat([df.iloc[:, 0] for df in [df_1, df_2]], axis=1, keys=['one', 'two'])
test_df.apply(lambda x: jd(x[0], x[1]), axis=1)
【讨论】:
以上是关于查找不同长度的两个 DataFrame 之间的相似性的主要内容,如果未能解决你的问题,请参考以下文章
两个非常相似的 Spark Dataframe 之间性能差异的可能原因
Pandas DataFrame 中的正则表达式 - 查找字符之间的最小长度