查找不同长度的两个 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 中的正则表达式 - 查找字符之间的最小长度

不同长度向量的余弦相似度?

Pyspark DataFrame:查找两个 DataFrame 之间的差异(值和列名)

查找两个不同数据框列之间的部分匹配,并在找到匹配时分配值