pandas 计算DataFrame列之间的Jaccard相似性

osh3o9ms  于 2023-03-16  发布在  其他
关注(0)|答案(2)|浏览(134)

下面是我的数据集:

我想迭代列来计算Jaccard similarity。顺便说一句,我对使用库来做这件事不感兴趣。
下面是我的代码:

def jaccard_binary(x,y):
    """A function for finding the similarity between two binary vectors"""
    intersection = np.logical_and(x, y)
    union = np.logical_or(x, y)
    similarity = intersection.sum() / float(union.sum())
    return similarity

for (columns) in df.items():
    jb = jaccard_binary(i, j)
    jac_sim = pd.DataFrame(jb, index=df.columns, columns=df.columns)
print(jac_sim)

但当然有些地方是错的,因为它显示了所有数据的相同值:

我做错了什么?我想这样做,因为我以后需要迭代列来执行其他公式,以计算其他事情。这就是为什么我需要迭代数据,但我不知道如何正确地做它。
下面也是我尝试过的,但它给“1”值的一切:

for i in range(0, len(df)):
    for j in range(0,len(df.columns)):
        jb = jaccard_binary(i, j)
        jac_sim = pd.DataFrame(jb, index=df.columns, columns=df.columns)
    print(jb)

谢谢!

5n0oy7gb

5n0oy7gb1#

在@J_H的回答的基础上,添加了一些代码来显示如何计算多行和多列的jaccard相似性

import pandas as pd

def jaccard_similarity(
    a: pd.Series,
    b: pd.Series,
):
    assert len(a) == len(b)  # should be a pair of columns from same dataframe
    total_size = len(a) + len(b)
    intersection = (a == b).sum()
    return intersection / (total_size - intersection)

df = pd.DataFrame(
    {
        "patient": ["P1", "P2", "P3", "P4", "P5"],
        "cancer":  [1, 1, 0, 0, 0],
        "thyroid": [1, 0, 0, 0, 0],
        "allergy": [0, 0, 0, 0, 0],
    }
)

# pairwise jaccard distance for rows
for row_index_1, row1 in df.iterrows():
    for row_index_2, row2 in df.iterrows():
        print(jaccard_similarity(row1, row2))

# pairwise jaccard distance for columns
for col1 in df:
    for col2 in df:
        print(jaccard_similarity(df[col1], df[col2]))
guz6ccqo

guz6ccqo2#

...迭代列以计算Jaccard相似性。
您希望使用相等运算符而不是逻辑AND。

import unittest

import pandas as pd

class JaccardTest(unittest.TestCase):
    def test_jaccard(self):
        df = _get_example_data()
        self.assertAlmostEqual(4 / 6, jaccard_similarity(df.cancer, df.thyroid))
        self.assertAlmostEqual(3 / 7, jaccard_similarity(df.cancer, df.allergy))

def jaccard_similarity(
    a: pd.Series,
    b: pd.Series,
):
    assert len(a) == len(b)  # should be a pair of columns from same dataframe
    total_size = len(a) + len(b)
    intersection = (a == b).sum()
    return intersection / (total_size - intersection)

def _get_example_data() -> pd.DataFrame:
    return pd.DataFrame(
        {
            "patient": ["P1", "P2", "P3", "P4", "P5"],
            "cancer":  [1, 1, 0, 0, 0],
            "thyroid": [1, 0, 0, 0, 0],
            "allergy": [0, 0, 0, 0, 0],
        }
    )

示例数据:

patient  cancer  thyroid  allergy
0      P1       1        1        0
1      P2       1        0        0
2      P3       0        0        0
3      P4       0        0        0
4      P5       0        0        0

在这个例子中,等式运算符给了我们一个五个布尔值的向量,然后我们把这些数字代入定义。
这是按照你的要求计算症状相似度的,很明显,如果有其他的要求,我们可以将病人的相似度与P1进行比较,取转置df.T,或者对行进行操作。

相关问题