如何在一定条件下按pandas数据帧分组

2024-05-26 11:12:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个熊猫数据帧如下

buyer_id item_id order_id        date
   139      57      387     2015-12-28
   140       9      388     2015-12-28
   140      57      389     2015-12-28
   36        9      390     2015-12-28
   64       49      404     2015-12-29
   146      49      405     2015-12-29
   81       49      406     2015-12-29
   140      80      407     2015-12-30
   139      81      408     2015-12-30

上面的数据帧中有很多行。我所要达到的目标是,是否推出新的菜品促使我的用户回归。item_id被映射到一个菜名。我想知道的是,某个特定的用户是否在不同的日子点了不同的菜。 e、 gbuyer_id 140 has ordered two dishes item_id (9,57) on 28th Dec and same buyer has ordered different dish (item_id = 80) on 30th Dec 然后我想将这个用户标记为1

我在python中是这样做的

^{pr2}$

它给出了以下输出

date        buyer_id
2015-12-28  139                 [57]
            140                 [9,57]     
            36                  [9]
2015-12-29  64                  [49]
            146                 [49]
            81                  [49]
2015-12-30  140                 [80]
            139                 [81]

期望输出

 buyer_id item_id order_id        date    flag
   139      57      387     2015-12-28     1
   140       9      388     2015-12-28     1
   140      57      389     2015-12-28     1
   36        9      390     2015-12-28     0
   64       49      404     2015-12-29     0 
   146      49      405     2015-12-29     0
   81       49      406     2015-12-29     0
   140      80      407     2015-12-30     1
   139      81      408     2015-12-30     1 

Tags: 数据用户id目标dateonorderbuyer
2条回答

类似于安东的回答,但是使用apply

users = df.groupby('buyer_id').apply(lambda r: r['item_id'].unique().shape[0] > 1 and 
                                               r['date'].unique().shape[0] > 1 )*1
df.set_index('buyer_id', inplace=True)
df['good_user'] = users

结果:

^{pr2}$

编辑因为我想到了另一个案例:假设数据显示一个买家在两个不同的日子里购买了相同的两个(或更多)商品。应该将此用户标记为1还是0?因为实际上,他/她在第二次约会时并没有做出任何不同的选择。 下表是81号买家。你看他们两次约会都只买49和50英镑。在

    buyer_id   item_id order_id    date
         139        57      387    2015-12-28
         140         9      388    2015-12-28
         140        57      389    2015-12-28
          36         9      390    2015-12-28
          64        49      404    2015-12-29
         146        49      405    2015-12-29
          81        49      406    2015-12-29
         140        80      407    2015-12-30
         139        81      408    2015-12-30
          81        50      406    2015-12-29
          81        49      999    2015-12-30
          81        50      999    2015-12-30

为了适应这种情况,我想出了一个办法(有点难看,但应该行得通)

# this function is applied to all buyers
def find_good_buyers(buyer):
    # which dates the buyer has made a purchase
    buyer_dates = buyer.groupby('date')
    # a string representing the unique items purchased at each date
    items_on_date = buyer_dates.agg({'item_id': lambda x: '-'.join(x.unique())})
    # if there is more than 1 combination of item_id, then it means that
    # the buyer has purchased different things in different dates
    # so this buyer must be flagged to 1
    good_buyer = (len(items_on_date.groupby('item_id').groups) > 1) * 1
    return good_buyer


df['item_id'] = df['item_id'].astype('S')
buyers = df.groupby('buyer_id') 

good_buyer = buyers.apply(find_good_buyers)
df.set_index('buyer_id', inplace=True)
df['good_buyer'] = good_buyer
df.reset_index(inplace=True)

这适用于buyer 81,将其设置为0,因为一旦按日期分组,进行采购的两个日期将具有相同的“49-50”采购项目组合,因此组合数量=1,买方将被标记为0。在

您可以按buyer_id分组,然后用np.unique聚合列。然后,您将得到np.ndarrays,其中包含多个日期和项目标识的行。您可以找到isinstancenp.ndarray的行,您将得到bool序列,您可以将其传递给聚合数据帧并找到感兴趣的买家。通过使用获得的buyers过滤原始数据帧,可以用loc填充flag的行:

df_agg = df.groupby('buyer_id')[['date', 'item_id']].agg(np.unique)
df_agg = df_agg.applymap(lambda x: isinstance(x, np.ndarray))

buyers = df_agg[(df_agg['date']) & (df_agg['item_id'])].index
mask = df['buyer_id'].isin(buyers)

df['flag'] = 0
df.loc[mask, 'flag'] = 1

In [124]: df
Out[124]: 
   buyer_id  item_id  order_id        date  flag
0       139       57       387  2015-12-28     1
1       140        9       388  2015-12-28     1
2       140       57       389  2015-12-28     1
3        36        9       390  2015-12-28     0
4        64       49       404  2015-12-29     0
5       146       49       405  2015-12-29     0
6        81       49       406  2015-12-29     0
7       140       80       407  2015-12-30     1
8       139       81       408  2015-12-30     1

第一步和第二步的输出:

^{pr2}$

相关问题 更多 >