我有一个像下面这样的pandas数据框
colspan=2
上面的数据框中有很多行。我想要实现的是,是否引入新菜肴驱使我的用户回来。 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
然后我想将此用户标记为buyer_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
我是如何在python中这样做的
1
它为我提供了以下输出
item_wise_order.groupby(['date','buyer_id'])['item_id'].apply(lambda x:
x.tolist())
期望的输出
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]
答案 0 :(得分:2)
与Anton的答案类似,但使用了应用
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
结果:
item_id order_id date good_user
buyer_id
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
编辑因为我想到了另一种情况:假设数据显示买家在两天内购买了相同的两件(或更多件)商品。此用户是否应标记为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)
这适用于买方81将其设置为0,因为一旦按日期分组,购买的两个日期将具有相同的“49-50”购买项目组合,因此组合数量= 1和买家将被标记为0。
答案 1 :(得分:1)
您可以按buyer_id
分组,然后使用np.unique
汇总列。然后,对于有多个日期和item_ids的行,您将获得np.ndarrays
。您可以找到isinstance
np.ndarray
的行,您将获得bool系列,您可以将其传递到聚合数据框并找到感兴趣的买家。通过使用获得的buyers
过滤原始数据框,您可以使用flag
填充loc
的行:
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
第一步和第二步的输出:
In [146]: df.groupby('buyer_id')[['date', 'item_id']].agg(np.unique)
Out[146]:
date item_id
buyer_id
36 2015-12-28 9
64 2015-12-29 49
81 2015-12-29 49
139 [2015-12-28, 2015-12-30] [57, 81]
140 [2015-12-28, 2015-12-30] [9, 57, 80]
146 2015-12-29 49
In [148]: df_agg.applymap(lambda x: isinstance(x, np.ndarray))
Out[148]:
date item_id
buyer_id
36 False False
64 False False
81 False False
139 True True
140 True True
146 False False