熊猫:计算密钥对之间的所有交集



我正在玩熊猫,我有一个问题,弄清楚如何解决以下问题。给定一个由bookId和readerId组成的数据框,我想获得对于给定的读者a来说,阅读过a所读过的任何一本书的其他读者的数量。

这是一个示例数据框架

import pandas as pd
df = pd.DataFrame({'bookId': [1,1,2,2,3,3,3,4,4,4,4,4],
                   'readerId': [1,2,1,3,1,3,4,1,3,4,5,6]})

有人能帮我解决这个问题吗?或者给我一些使用熊猫时解决这个问题的直觉?输出一个带有readerId和count列的新数据帧。

更新:

实际上,与其得到每本书的读者数量,我更想得到所有读过我读过的书的读者数量。因此,如果一个读者读了3本书,另外20个人读了其中的任何一本书,那么我真的想要20个作为答案,如果这20个读者都是不同的,并且不一定读了给定读者的所有书单。

要获取每个阅读器的计数,应该这样做:

In [1]: import pandas as pd
In [2]: df = pd.DataFrame({'bookId': [1,1,2,2,3,3,3,4,4,4,4,4],
   ...:                  'readerId': [1,2,1,3,1,3,4,1,3,4,5,6]})
In [3]: res = pd.DataFrame(np.unique(df.readerId)).reset_index(drop=True)
In [4]: def get_readers(reader, df=df):
    ...:     return len(set(df.readerId[df.bookId.isin(df.bookId[
    ...:                                     df.readerId==reader])]))-1
In [5]: res['Count'] = res.readerId.apply(get_readers)
In [6]: res
Out[6]: 
   readerId  Count
0         1      5
1         2      1
2         3      4
3         4      4
4         5      4
5         6      4
In [7]: timeit get_readers(1)
1000 loops, best of 3: 387 us per loop

应该有很多方法可以解决你的问题。这是我的,可能不是最好的:

首先,获取reader1

的bookIds
In [99]: bookIds = df[df['readerId']==1]['bookId'].values
In [100]: bookIds
Out[100]: array([1, 2, 3, 4]) 

如果您熟悉SQL,您可以将其视为:SELECT bookId FROM df WHERE readerId == 1

其次,选择readerId == 1和bookId在上述bookIds数组

In [101]: df2 = df[df['readerId'] != 1 & df['bookId'].isin(bookIds)]
In [102]: df2 
Out[102]: 
    bookId  readerId
1        1         2   
3        2         3   
5        3         3   
6        3         4   
8        4         3   
9        4         4   
10       4         5   
11       4         6   

SQL: SELECT bookId, readerId FROM df WHERE readerId != 1 and bookId in bookIds

最后,按readerId分组并计数

In [103]: df2.groupby('readerId').size()
Out[103]: 
readerId
2           1   
3           3   
4           2   
5           1
6           1
dtype: int64

SQL: SELECT COUNT(bookId) FROM df2 GROUP BY readerId

希望它能帮助你更容易地了解熊猫

[编辑],回答你在评论中提出的问题:

创建另一个数据框(只更改列)

In [114]: df2 = df.rename(columns={'readerId': 'otherReaderId'})

通过bookId将它们连接,然后通过readerIdotherReaderId将它们分组

In [115]: pd.merge(df, df2, on='bookId').groupby(['readerId', 'otherReaderId']).size()
Out[115]: 
readerId  otherReaderId
1         1                4
          2                1
          3                3
          4                2
          5                1
          6                1
2         1                1
          2                1
3         1                3
          3                3
          4                2
          5                1
          6                1
4         1                2
          3                2
          4                2
          5                1
          6                1
5         1                1
          3                1
          4                1
          5                1
          6                1
6         1                1
          3                1
          4                1
          5                1
          6                1
dtype: int64

最新更新