我有一个大数据框(1M 行),有两列 A、B。
对于 A 的每一对 a_i, a_j,我想知道 B 中 b 的数量,使得同时存在行 a_i,b 和 a_j,b
例如:
A | 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
结果将是以下矩阵(根据定义,该矩阵是对称的):
a1 | a2 | a3 | 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)
但是它需要太多的时间和内存,并且不能与我的 1M 行一起运行。此外,对角线是计算出来的,而我不需要它,而且我认为通过虚拟值并不是一个好主意,特别是因为生成的二进制文件非常稀疏。
但我没有更多的想法了...
你有什么建议?
编辑:
为了了解更多背景信息,我们假设 A 是学生,B 是课程。 最后我想知道对于任何两个学生来说,他们总共有多少课程。对于每对至少共享一门课程的学生来说也是如此。 如果这更有意义:)
尝试使用
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