在python中使用datetime列从数据框的子集创建记录表



为Python中的pandas DataFrame:

<表类> ID 日期 方向 tbody><<tr>02022-01-03 10:00:0102022-01-03 11:00:0102022-01-03 11:10:01出02022-01-03 12:00:0302022-01-03 14:32:01出12022-01-03 10:32:01出12022-01-04 11:32:0112022-01-04 14:32:01出22022-01-02 08:00:01出22022-01-02 08:02:01

我不确定我是否完全理解,但这里有一个尝试。

沿着date列(date应该是datetime)排序后:在ID上分组,然后分三步消除所有不符合所需模式的行:在每组开始时消除OUT块。2. 将每组IN/OUT的连续块减少到第一个。3.如果组的最后一行是IN-row,则删除它。剩下的基本上是将结果数据帧分割成两个交错的部分,并将它们连接到另一个部分。

def connect(df):
df = df[df["direction"].cummax()]
df = df[df["direction"].diff().fillna(True)]
if df.shape[0] % 2:
df = df.iloc[:-1]
return df
result = (
df
.assign(direction=df["direction"].replace({"IN": True, "OUT": False}))
.sort_values(["ID", "date"])
.groupby("ID").apply(connect)
.drop(columns="direction")
.droplevel(-1, axis=0)
)
result = pd.concat(
[result.iloc[0::2], result[["date"]].iloc[1::2]], axis=1
).reset_index(drop=True)
result.columns = ["ID", "entry_date", "exit_date"]

结果:

ID          entry_date           exit_date
0   0 2022-01-03 10:00:01 2022-01-03 11:10:01
1   0 2022-01-03 12:00:03 2022-01-03 14:32:01
2   1 2022-01-04 11:32:01 2022-01-04 14:32:01

另一个解决方案是按ID分组,然后,在每组中,将directions分成2个堆栈,insouts,并通过它们运行以收集连接:

def connect(df):
mask = df["direction"].eq("IN")
ins = list(reversed(df.loc[mask, "date"].values))
outs = list(reversed(df.loc[~mask, "date"].values))
connects = []
if ins:
dt_out = ins[-1] + pd.Timedelta(days=-1)
while ins and outs:
dt_in = None
while ins:
dt = ins.pop()
if dt > dt_out:
dt_in = dt
break
while dt_in and outs:
dt_out = outs.pop()
if dt_in < dt_out:
connects.append([dt_in, dt_out])
break
return pd.DataFrame(
connects, columns=["entry_date", "exit_date"]
)
result = (
df.sort_values(["ID", "date"]).groupby("ID").apply(connect)
.droplevel(1, axis=0).reset_index()
)

最新更新