熊猫:计算一对钥匙之间的所有交叉点

时间:2013-05-31 03:01:04

标签: python pandas

我正在玩大熊猫,我遇到了解决如何解决以下问题的问题。给定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位读者都是截然不同的,并不一定能阅读所有给定读者的书单。

2 个答案:

答案 0 :(得分:2)

为了获得每个读者的计数,这样的事情应该有效:

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

答案 1 :(得分:1)

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

首先,获取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