在数据框上应用过滤器功能

时间:2019-04-07 19:32:46

标签: python pandas

我有一个市场上的销售和购买数据集,看起来像这样。

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')

1 个答案:

答案 0 :(得分:1)

执行此操作的一种可能方法是使用groupby,然后像汇总this SO post中所示在每个组中简单列出Transaction_Type,而不是进行汇总。然后,只需获取列表的长度即可。...如果长度为2,则表示该用户同时存在SalePurchase。另一方面,如果长度为1,则该用户仅出现SalePurchase中的一个。

为每个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