如何在给定日期之前和之后计算数据框中的事件数?



我正在尝试识别在他们第一次发生特定类型事件之前或之后发生事件的个人。

例如,我对类型为"y"的事件感兴趣。我想知道哪些人在第一次与类型为"y"的事件相关联之前或之后经历过类型为"x"、"z"、"p"等的事件。

输入数据帧的示例如下:

df=pd.DataFrame({'IDs':['a','a','a','b','b','c'],'Event_types':['x','y','z','p','y','x'],'date':['2020-01-01','2020-01-06','2020-01-11','2020-01-11','2020-01-14','2020-01-27']})

给:

IDs Event_types       date
0   a           x 2020-01-01
1   a           y 2020-01-06
2   a           z 2020-01-11
3   b           p 2020-01-11
4   b           y 2020-01-14
5   c           x 2020-01-27

如果我关注类型为'y的事件,那么期望的输出将是

IDs  Event_type_x_before  Event_type_x_after  Event_type_z_before  Event_type_z_after
0   a                    1                   0                    0                   1
1   b                    0                   0                    0                   0
2   c                    0                   1                    0                   0

我发现的最佳解决方案是Pandas按组计算事件在过去n天内发生的次数,这与我想要的接近,但它对于数据帧的大小运行太慢,并且只处理过去的事件(或未来,如果时间增量被修改)。如有任何帮助,不胜感激。

使用以下玩具数据帧(比您的示例多一个):

import pandas as pd
df = pd.DataFrame(
{
"IDs": ["a", "a", "a", "b", "b", "c", "c"],
"Event_types": ["x", "y", "z", "p", "y", "x", "x"],
"date": [
"2020-01-01",
"2020-01-06",
"2020-01-11",
"2020-01-11",
"2020-01-14",
"2020-01-27",
"2020-01-28",
],
}
)

有一种方法:

# Setup
TARGET = "y"
first_occurrence = df.loc[df["Event_types"] == TARGET, "date"].min()
# Count number of events before/after TARGET event
df = (
df.loc[~(df["Event_types"] == TARGET), :]
.assign(before=lambda df_: (df_["date"] < first_occurrence).astype(int))
.assign(after=lambda df_: (df_["date"] >= first_occurrence).astype(int))
.groupby(["IDs", "Event_types"])
.sum()
.reset_index()
)
# Create new dataframe
new_df = pd.DataFrame()
for idx in df["IDs"].unique():
for evt in df["Event_types"].unique():
mask = (df["IDs"] == idx) & (df["Event_types"] == evt)
try:
new_df.loc[idx, f"{evt}_before_{TARGET}"] = df.loc[mask, "before"].values[0]
except Exception:
pass
try:
new_df.loc[idx, f"{evt}_after_{TARGET}"] = df.loc[mask, "after"].values[0]
except Exception:
pass
# Cleanup
new_df = new_df.fillna(0).astype(int)
print(new_df)
# Output
x_before_y  x_after_y  z_before_y  z_after_y  p_before_y  p_after_y
a           1          0           0          1           0          0
b           0          0           0          0           0          1
c           0          2           0          0           0          0

最新更新