numpy 在pandas矩阵中,对A的每个a_i,a_j,计算a_i和a_j与b相同的次数,

svmlkihl  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(118)

我有一个大的框架(1 M线),有两列A,B。
对于A的每一对a_i,a_j,我想知道B中b的个数,使得既有a_i,b行,也有a_j,b行
举例来说:
| 一|B|
| --|--|
| A1| B1|
| A2| B1|
| A3| B2|
| A1| B3|
| A3| B3|
| A4| B3|
| A2| B4|
| A1| B5|
| A3| B5|
| A3| B6|
| A4| B6|
这里有一对a1,a3,它们共用b3和b5
结果将是以下矩阵(根据定义,是对称的):
| | A2| A3| A4| a4 |
| --|--|--|--|--|
| A1| xx| 1 | 2 | 1 |
| A2| 1 |xx| 0 | 0 |
| A3| 2 | 0 |xx| 2 |
| A4| 1 | 0 | 2 |xx|
我认为以下做法可行:

df = pd.DataFrame({'A' : ['a1','a2','a3','a1','a3','a4','a2','a1','a3','a3','a4'],
 'B':['b1','b1','b2','b3','b3','b3','b4','b5','b5','b6','b6']})

df_dum = df.set_index('A')['B'].str.get_dummies().reset_index()
df_dum = df_dum.groupby('A').sum()
np_cnt = df_dum.to_numpy()
np_mul = np.matmul(np_cnt,np_cnt.T)

字符串
但是它占用了太多的时间和内存,而且不能在我的1 M行上运行。另外,对角线是计算的,而我不需要它,我认为通过虚拟对象不是一个好主意,特别是因为得到的二进制文件非常稀疏。
但我没有别的想法了...
你有什么建议
编辑:
为了更好地了解上下文,我们假设A是学生,B是课程。最后我想知道任何两个学生,他们一起有多少课程。以及每两个学生至少共享一门课程。如果这样更有意义:)

ohtdti5x

ohtdti5x1#

使用itertools.permutations

import itertools

sets = df.groupby('B')['A'].apply(lambda x : list(itertools.permutations(x, 2))).explode().tolist()
sets = pd.DataFrame(sets)

index = df["A"].unique()
output = pd.crosstab(sets[0],sets[1],rownames=[None],colnames=[None]).reindex(index).reindex(index, axis=1)

>>> output
    a1  a2  a3  a4
a1   0   1   2   1
a2   1   0   0   0
a3   2   0   0   2
a4   1   0   2   0

字符串
如果你想用“xx”屏蔽index和columns相同的单元格:

output = output.mask(output.index.values[:,None] == output.columns.values[None,:]).fillna("xx")

>>> output
     a1   a2   a3   a4
a1   xx  1.0  2.0  1.0
a2  1.0   xx  0.0  0.0
a3  2.0  0.0   xx  2.0
a4  1.0  0.0  2.0   xx

hi3rlvi2

hi3rlvi22#

使用较小表格的矩阵乘法:

import numpy as np

s = df.pivot_table(index = 'A', columns = 'B', aggfunc=len, fill_value=0)
t = s @ s.T
np.fill_diagonal(t.to_numpy(), 0)
t
A   a1  a2  a3  a4
A                 
a1   0   1   2   1
a2   1   0   0   0
a3   2   0   0   2
a4   1   0   2   0

字符串
请注意,你可以用任何你想要的东西来填充对角线,或者最好不要用它。

相关问题