计算两个数据帧中每个用户的事件数



我试图计算表中每个用户过去发生的事件数。实际上,我有两个数据帧,一个用于特定时间点'T'的每个用户,一个用于也在时间点发生的每个事件。

下面是用户表的示例:

ID_CLIENT   START_DATE
0   A   2015-12-31
1   A   2016-12-31
2   A   2017-12-31
3   B   2016-12-31

事件表的示例:

ID_CLIENT   DATE_EVENT
0   A   2017-01-01
1   A   2017-05-01
2   A   2018-02-01
3   A   2016-05-02
4   B   2015-01-01

这个想法是,我希望在"user">

在"start_date"上注册的日期之前发生的事件计数。最终结果示例:

ID_CLIENT   START_DATE  nb_event_tot
0   A   2015-12-31  0
1   A   2016-12-31  1
2   A   2017-12-31  3
3   B   2016-12-31  1

我已经创建了一个函数,利用".apply"熊猫的功能,但是太慢了…如果有人有一个关于如何加快它的想法,我将不胜感激。我有800K的用户行和200k的事件行,使用apply方法需要长达3个小时。

下面是我要复制的代码:
import pandas as pd
def check_below_df(row, df_events, col_event):
# Select the ids
id_c = row['ID_CLIENT']
date = row['START_DATE']
# Select subset of events df
sub_df_events = df_events.loc[df_events['ID_CLIENT'] == id_c, :]
sub_df_events = sub_df_events.loc[sub_df_events[col_event] <= date, :]
count = len(sub_df_events)
return count

def count_events(df_clients: pd.DataFrame, df_event: pd.DataFrame, col_event_date: str = 'DATE_EVENEMENT',
col_start_date: str = 'START_DATE', col_end_date: str = 'END_DATE', col_event:str = 'nb_sin', events = ['compensation']):
df_clients_cp = df_clients[["ID_CLIENT", col_start_date]].copy()
df_event_cp = df_event.copy()
df_event_cp[col_event] = 1

# TOTAL
df_clients_cp[f'{col_event}_tot'] = df_clients_cp.apply(lambda row: check_below_df(row, df_event_cp, col_event_date), axis=1)
return df_clients_cp
# ------------------------------------------------------------------
# ------------------------------------------------------------------
df_users = pd.DataFrame(data={
'ID_CLIENT': ['A', 'A', 'A', 'B'],
'START_DATE': ['2015-12-31', '2016-12-31', '2017-12-31', '2016-12-31'],

})
df_users["START_DATE"] = pd.to_datetime(df_users["START_DATE"])
df_events = pd.DataFrame(data={
'ID_CLIENT': ['A', 'A', 'A', 'A', 'B'],
'DATE_EVENT': ['2017-01-01', '2017-05-01', '2018-02-01', '2016-05-02', '2015-01-01']
})
df_events["DATE_EVENT"] = pd.to_datetime(df_events["DATE_EVENT"])

tmp = count_events(df_users, df_events, col_event_date='DATE_EVENT', col_event='nb_event')
tmp

谢谢你的帮助。

我猜是由pd.apply(axis=1)引起的,这里有解释。

我估计您可以通过使用不按行应用的函数来改进执行时间,例如通过使用merge和groupby。

首先我们合并帧:

df_merged = pd.merge(df_users, df_events, on='ID_CLIENT', how='left')

然后我们检查整个帧的DATE_EVENT<=START_DATE:

df_merged.loc[:, 'before'] = df_merged['DATE_EVENT'] <= df_merged['START_DATE'] 

然后按CLIENT_IDSTART_DATE分组,对'before'列求和:

df_grouped = df_merged.groupby(by=['ID_CLIENT', 'START_DATE'])
df_out = df_grouped['before'].sum()  # returns a series

最后,我们将df_out(一个序列)转换回一个数据框,将新列重命名为'nb_event_tot',然后重置索引以获得所需的输出:

df_out = df_out.to_frame('nb_event_tot')
df_out = df_out.reset_index()

最新更新