如何在pandas中计算共享唯一字段的行数

3
假设我有一个数据框,记录了个人阅读的书籍及其得分情况:
df = pd.DataFrame({
'person' : [1,1,2,2,3,3], 
'book' : ['dracula', 'frankenstein', 'dracula', 'frankenstein',   'dracula', 'rebecca'], 
'score':[10,11,12,13,14,15]
})

df

           book  person  score
0       dracula       1     10
1  frankenstein       1     11
2       dracula       2     12
3  frankenstein       2     13
4       dracula       3     14
5       rebecca       3     15

我想要一个数据框,显示每对书籍有多少人都阅读过,即期望的结果如下:
               dracula    frankensten   rebecca
dracula          3             2           1
frankenstein     2             2           0
rebecca          1             0           1

也就是说,有两个人都读过draculafrankenstein,一个人读过dracularebecca等等。我不关心分数。

我感觉这与数据透视表/堆叠/展开有关,但无法弄清楚,有什么建议吗?

2个回答

3
你可以构建一个数据透视表,并将其与其转置相乘:
pvt = pd.pivot_table(df, index='book',  columns='person', aggfunc=len, fill_value=0)
pvt.dot(pvt.T)
Out: 
book          dracula  frankenstein  rebecca
book                                        
dracula             3             2        1
frankenstein        2             2        0
rebecca             1             0        1

2

使用crosstab的另一个解决方案:

df = pd.crosstab(df.book, df.person)
print (df.dot(df.T))
book          dracula  frankenstein  rebecca
book                                        
dracula             3             2        1
frankenstein        2             2        0
rebecca             1             0        1

或者使用 groupbyunstack 解决方案:

df = df.groupby(['book','person'])['person'].size().unstack().fillna(0).astype(int)
print (df.dot(df.T))
book          dracula  frankenstein  rebecca
book                                        
dracula             3             2        1
frankenstein        2             2        0
rebecca             1             0        1

太棒了,感谢您提供这两个解决方案 - 我发现groupby更熟悉,但显然这正是crosstab所用的问题类型,所以我会努力学习它。 - mojones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接