计算具有不同长度的DataFrame列之间的Jaccard相似性

时间:2017-08-15 11:34:23

标签: python python-2.7 pandas scikit-learn

我有一个数据框,其中user_ids为列,以及他们喜欢作为行值的电影的ID。这是一个片段:

   15       30       50        93       100     113      1008    1028    
0  3346.0  42779.0   1816.0  191319.0    138.0   183.0    171.0   283.0   
1  1543.0      NaN    169.0    5319.0  34899.0   188.0  42782.0  1183.0   
2  5942.0      NaN  30438.0  195514.0    169.0   172.0    187.0  5329.0   
3  3249.0      NaN  32361.0     225.0     87.0   547.0   6710.0   283.0   
4   794.0      NaN    187.0  195734.0   6297.0  8423.0   1289.0   222.0   

我试图计算每列之间的Jaccard相似度(即每个用户之间使用他们喜欢的电影)。当我尝试使用sklearn中的jaccard_similarity_score时,Python会出现以下错误:

ValueError: continuous is not supported

理想情况下,我希望获得一个包含user_id的行和列的矩阵,并将值作为每个的相似度得分。

如何计算这些列之间的jaccard相似度?我曾尝试使用带有键的字典列表作为用户ID和值作为电影列表,但它需要永远计算。

1 个答案:

答案 0 :(得分:0)

由于sklearn.metrics.jaccard_similarity_score需要两个相等长度的输入向量,您可以尝试类似以下内容,部分地从this类似问题中添加。

import itertools
import pandas as pd

# Method to compute Jaccard similarity index between two sets
def compute_jaccard(user1_vals, user2_vals):
    intersection = user1_vals.intersection(user2_vals)
    union = user1_vals.union(user2_vals)
    jaccard = len(intersection)/float(len(union))
    return jaccard

# Small test dataframe
users = ['user1', 'user2', 'user3']
df = pd.DataFrame( 
    np.transpose(np.array([[1,2,3],[3,np.NAN,7], [np.NAN, np.NAN,3]])), 
    columns=users)
sim_df = pd.DataFrame(columns=users, index=users)

# Iterate through columns and compute metric
for col_pair in itertools.combinations(df.columns, 2):
    u1= col_pair[0]
    u2 = col_pair[1]
    sim_df.loc[col_pair] = compute_jaccard(set(df[u1].dropna()), set(df[u2].dropna()))


print sim_df

这将返回相似性矩阵的以下(上三角形)一半,其中对角线当然都是1。

        user1  user2     user3
user1   NaN    0.25      0.333333
user2   NaN    NaN       0.5
user3   NaN    NaN       NaN