我有一个市场上的销售和购买数据集,看起来像这样。
User_ID | Transaction_Type | Date | Amount
1 | Sale | 01/01/14 | 200.00
2 | Purchase | 01/01/14 | 30.00
...
我需要筛选出仅购买或出售某物的客户与至少购买或出售某物的客户。
我正在尝试创建一个函数,该函数将检查用户是否同时执行了两个操作。如果用户同时完成这两项操作,则该用户将被标记为是,否则标记为否。
到目前为止,我已经尝试过这样做,
def user_filter(df):
if df in df['User_ID'].filter(lambda x : ((x['Transaction_Type']=='Sale').any())&((x['Transaction_Type']=='Purchase').any())):
return 'yes'
else:
return 'no'
df['cross'] = df['User_ID'].apply(user_filter)
让我们稍后在数据集中假设User_ID 1将作为购买返回。我希望它会返回为:
User_ID | Transaction_Type | Date | Amount | cross
1 | Sale | 01/01/14 | 200.00 | yes
2 | Purchase | 01/01/14 | 30.00 | no
但返回以下错误:
'int' object is not subscriptable
当我将其应用于整个数据框而不是系列时,它返回:
KeyError: ('User_ID', 'occurred at index User_ID')
答案 0 :(得分:1)
执行此操作的一种可能方法是使用groupby
,然后像汇总this SO post中所示在每个组中简单列出Transaction_Type
,而不是进行汇总。然后,只需获取列表的长度即可。...如果长度为2,则表示该用户同时存在Sale
和Purchase
。另一方面,如果长度为1,则该用户仅出现Sale
或Purchase
中的一个。
为每个OP生成一些数据(我添加了第三条记录以使输出更明确)
d = [['User_ID', 'Transaction_Type', 'Date', 'Amount'],
[1, 'Sale', '01/01/14', 200],
[1, 'Purchase','01/02/14',300],
[2, 'Purchase','01/01/14',30],]
执行GROUP BY
df_users = df.groupby('User_ID')['Transaction_Type'].apply(list).reset_index(drop=False)
df_users.rename(columns={'Transaction_Type':'Transactions'}, inplace=True)
print(df_users)
User_ID Transactions
0 1 [Sale, Purchase]
1 2 [Purchase]
现在将cross
列追加到分组的DataFrame
并根据需要填充cross
列
df_users['cross'] = 'no'
df_users.loc[df_users.Transactions.apply(len)==2, 'cross'] = 'yes'
print(df_users)
User_ID Transactions cross
0 1 [Sale, Purchase] yes
1 2 [Purchase] no
编辑1
或者,放弃apply
步骤,只使用size
df_users = df.groupby('User_ID')['Transaction_Type'].size().reset_index(drop=False)
df_users['cross'] = 'no'
df_users.loc[df_users.Transactions==2, 'cross'] = 'yes'
print(df_users)
User_ID Transactions cross
0 1 2 yes
1 2 1 no
编辑2
如果您想将cross
列附加到源DataFrame
,则将这两行代码添加到上面
df = df.merge(df_users, on='User_ID')
df.drop(columns=['Transactions'], inplace=True)
print(df)
User_ID Transaction_Type Date Amount cross
0 1 Sale 01/01/14 200 yes
1 1 Purchase 01/02/14 300 yes
2 2 Purchase 01/01/14 30 no