首页 > 解决方案 > Pandas,查找行组合出现在不同列 ID 下的次数

问题描述

我有一个如下所示的数据集:

df = pd.DataFrame({'purchase': [1, 1, 2, 2, 2, 3],
                   'item': ['apple', 'banana', 'apple', 'banana', 'pear', 'apple']})
df

   purchase    item
0         1   apple
1         1  banana
2         2   apple
3         2  banana
4         2   pear
5         3    apple  

我需要一个输出,例如

item_1 item_2 购买
苹果 香蕉 2
香蕉 1
苹果 1

一张表格计算在同一购买中购买了两种水果组合的次数。

在此示例的第一行中,值为applebanana2因为有两次购买(请参阅列purchase),购买 ID 1 和购买 ID 2,其中该人同时购买了苹果和香蕉。第二行是applepear1,因为只有一次购买(购买 ID 2),该人同时购买了 apple 和 pear。

到目前为止我的代码:

df = pd.DataFrame({'purchase': [1, 1, 2, 2, 2, 3],
                   'item': ['apple', 'banana', 'apple', 'banana', 'pear', 'apple']})
dummies = pd.get_dummies(df['item'])
df2 = pd.concat([df['purchase'], dummies], axis=1)

像这样创建一个表:

   purchase  apple  banana  pear
0         1      1       0     0
1         1      0       1     0
2         2      1       0     0
3         2      0       1     0
4         2      0       0     1
5         3      1       0     0

现在,我不知道如何继续获得想要的结果(而且我知道我的输出与想要的结果相去甚远)。我尝试了一些 group by,但没有成功。

标签: pythonpandasdataframe

解决方案


这是另一个使用joinwith duplicated index 的行为:

df2 = df.set_index("purchase")
df2 = df2.join(df2, rsuffix="_other")\
  .groupby(["item", "item_other"])\
  .size().rename("count").reset_index()
result = df2[df2.item < df2.item_other].reset_index(drop=True)

#      item item_other  count
# 0   apple     banana      2
# 1   apple       pear      1
# 2  banana       pear      1

combinations在以下基准测试中,与使用 builtin 相比,我得到了大约 10 倍的加速:

import numpy as np

num_orders = 200
max_order_size = 10
num_items = 50

purchases = np.repeat(np.arange(num_orders), 
                      np.random.randint(1, max_order_size, num_orders))
items     = np.random.randint(1, num_items, size=purchases.size)

test_df = pd.DataFrame({
    "purchase": purchases,
    "item": items,
})

推荐阅读