首页 > 解决方案 > 具有不重叠条目集的两列值的共现表

问题描述

import pandas as pd

可重现的设置

我有一个数据框:

df=\
pd.DataFrame.from_dict({'A':['a','b','b','c','d','d','c','b'],
                        'B':['p','q','p','q','r','r','p','q']})

IE

   A  B
0  a  p
1  b  q
2  b  p
3  c  q
4  d  r
5  d  r
6  c  p
7  b  q

如果一个值出现在 column 中B,它肯定不会出现在 column 中A,反之亦然。来自 pandas 数据框的 post Cooccurence matrix讨论了类似的设置,但有重要区别:输入和输出的形式不同(尽管信息内容相似)。与我当前的帖子不同,它也不需要列具有不同的条目集。


目标

我想创建一个新的数据框,它显示每个条目与来自A的每个条目一起出现的次数A。我希望这个新数据框的列是来自df's column 的条目A,所以结果如下所示:

res=\
pd.DataFrame.from_dict({'B':['p','q','r'],
                        'a':[1,0,0],
                        'b':[1,2,0],
                        'c':[1,1,0],
                        'd':[0,0,2]})

IE:

   B  a  b  c  d
0  p  1  1  1  0
1  q  0  2  1  0
2  r  0  0  0  2

问题

如何转换df为上述数据框?


我试过的

一个)

使用这个问题的答案Group by two columns 并计算 Pandas 中每个组合的出现次数,我想出了:

df.groupby(['A','B']).size().to_frame(name = 'size').reset_index()

IE

   A  B  size
0  a  p     1
1  b  p     1
2  b  q     2
3  c  p     1
4  c  q     1
5  d  r     2

这是相似的,但形式不同。可能可以将其转换为我的形式,但可能存在更有效的方法。


二)

基于,尝试:

df.pivot_table('A', aggfunc='count').fillna(0)

但这给了ValueError: No group keys passed!. 我不确定链接的帖子是否在发布的地方工作,所以我放弃了这条路。


C)

根据对此问题Cooccurence matrix from pandas dataframe的回答,我想出了这个:

s=df.stack().str.get_dummies().sum(level=0).ne(0).astype(int)
s=s.T.dot(s).astype(float)
np.fill_diagonal(s.values, np.nan)
s=s[['a','b','c','d']].drop(index=['a','b','c','d'])
s.index.name = 'B'
s=s.astype(int)
s.reset_index(inplace=True)

IE

   B  a  b  c  d
0  p  1  1  1  0
1  q  0  2  1  0
2  r  0  0  0  2

这就是我想要的。然而,它是相当复杂和漫长的解决方案。我更喜欢更紧凑的。

标签: pythonpandas

解决方案


使用交叉表

import pandas as pd

df = pd.DataFrame.from_dict(
    {
        "A": ["a", "b", "b", "c", "d", "d", "c", "b"],
        "B": ["p", "q", "p", "q", "r", "r", "p", "q"],
    }
)

res = pd.crosstab(df['B'], df['A'])
print(res)

输出

A  a  b  c  d
B            
p  1  1  1  0
q  0  2  1  0
r  0  0  0  2

推荐阅读