我试图在python中创建一个共现矩阵,但是正在寻找一些有效的方法来实现它。
我的数据集如下:
total_labels = ['a','b','c','d']
occ = [['a','b'],['c','d'],['a','c'],['d'],['a','c','d']]
我期望这样的输出:
data_mat = [[0, 1 , 2, 1],
[1, 0, 0, 0],
[2, 0, 0, 2],
[1, 0, 2, 0]]
实际上是:
a b c d
data_mat = a [[0, 1 , 2, 1],
b [1, 0, 0, 0],
c [2, 0, 0, 2],
d [1, 0, 2, 0]]
我尝试过的是:
import numpy as np
m_matrix = np.zeros([4,4])
for m in range(len(total_labels)):
for j in range(len(total_labels)):
for k in occ:
if set((total_labels[m],total_labels[j])).issubset(set(k)):
m_matrix[m,j]+=1
正在提供:
array([[3., 1., 2., 1.],
[1., 1., 0., 0.],
[2., 0., 3., 2.],
[1., 0., 2., 3.]])
但是正如您所看到的,(a,a)和(b,b)等之间(自循环)之间没有任何联系,但是它在那里提供了值。
如何在不使用很多循环的情况下创建data_mat?
答案 0 :(得分:1)
自我-merge
后跟crosstab
import pandas as pd
df = pd.DataFrame(occ).stack().rename('val').reset_index().drop(columns='level_1')
df = df.merge(df, on='level_0').query('val_x != val_y')
pd.crosstab(df.val_x, df.val_y)
val_y a b c d
val_x
a 0 1 2 1
b 1 0 0 0
c 2 0 0 2
d 1 0 2 0
如果仅需要您提供的那些标签即可:
(pd.crosstab(df.val_x, df.val_y)
.reindex(total_labels, axis=0).reindex(total_labels, axis=1))
或在合并之前进行过滤(可能更聪明):
df = df.loc[df.val.isin(total_labels)]