我有一个这样的数据框。
id | 行动 | enc |
---|---|---|
细胞1 | 跑步、游泳、步行 | 1,2,3 |
细胞2 | 游泳、爬山、冲浪、健身 | 2,4,5,6 |
细胞3 | 慢跑、跑步] | 7,1 |
该表大约有 30k 行。收集所有这些操作并使用 labelencoder 进行编码后。
我想创建一个相似性矩阵,我可以用它来将具有相似动作的细胞聚集在一起。
我尝试使用
pairwise_distances(df['enc'],metric='jaccard')
,但遇到了设置数组元素错误。填充它对我来说也没有多大意义。
有没有办法基于jaccard生成相似度矩阵?谢谢。
第 1 步,这是您的数据框
import pandas as pd
data = [['Cell 1', ['run','swim','walk'], [1,2,3]], ['Cell 2', ['swim','climb','surf','gym'], [2,4,5,6]], ['Cell 3', ['jog','run'], [7,1]]]
df = pd.DataFrame(data, columns=['id', 'action', 'label_encoder'])
print(df)
id action label_encoder
0 Cell 1 [run, swim, walk] [1, 2, 3]
1 Cell 2 [swim, climb, surf, gym] [2, 4, 5, 6]
2 Cell 3 [jog, run] [7, 1]
第2步,添加one_hot列表作为新列
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
one_hot = mlb.fit_transform(df['label_encoder'])
# add one_hot list as a new column
df['label_encoder_one_hot'] = list(one_hot)
print(df)
id action labelen_coder label_encoder_one_hot
0 Cell 1 [run, swim, walk] [1, 2, 3] [1, 1, 1, 0, 0, 0, 0]
1 Cell 2 [swim, climb, surf, gym] [2, 4, 5, 6] [0, 1, 0, 1, 1, 1, 0]
2 Cell 3 [jog, run] [7, 1] [1, 0, 0, 0, 0, 0, 1]
第3步,基于Jaccard生成相似度矩阵
from sklearn.metrics import jaccard_score
import numpy as np
similarity_matrix = np.zeros((len(df), len(df)))
for i in range(len(df)):
for j in range(i+1, len(df)):
similarity = jaccard_score(df['label_encoder_one_hot'][i], df['label_encoder_one_hot'][j])
similarity_matrix[i,j] = similarity
similarity_matrix[j,i] = similarity
print(similarity_matrix)
[[0. 0.16666667 0.25 ]
[0.16666667 0. 0. ]
[0.25 0. 0. ]]
您可以使用
itertools.combinations
和 python set
操作:
from itertools import combinations
from scipy.spatial.distance import squareform
s = df['enc'].str.split(',').apply(set)
tmp = squareform([len(a&b)/len(a|b) for a,b in combinations(s, 2)])
idx = df['id'].tolist()
out = pd.DataFrame(tmp, index=idx, columns=idx)
输出:
Cell 1 Cell 2 Cell 3
Cell 1 0.000000 0.166667 0.25
Cell 2 0.166667 0.000000 0.00
Cell 3 0.250000 0.000000 0.00