[英]How to use date_range with day frequency?
我嘗試在此date_range
上使用日期范圍和day
頻率:
df = pd.DataFrame({'Start':['2022-06-07 06:24:48','2022-06-07 14:37:16','2022-06-07 08:00:59'],
'End':['2022-06-07 14:07:00','2022-06-08 02:51:21','2022-06-09 13:18:34'],
'Process':['PROD','VORG','STO'],
'Duration_Min':[462.20,734.08,3197.58]})
df['Start'] = pd.to_datetime(df['Start'])
df['End'] = pd.to_datetime(df['End'])
df['difference']=df['End'].dt.date-df['Start'].dt.date
def find_interval(sr):
dti = pd.date_range(sr['Start'], sr['End'], freq='1D').normalize() + pd.Timedelta(days=1)
return list(zip([sr['Start']] + dti.tolist(), dti.tolist() + [sr['End']]))
df1 = df.apply(find_interval, axis=1).explode().apply(pd.Series)
df1 = df.drop(columns=['Start', 'End']).join(df1).rename(columns={0: 'Start', 1: 'End'})
df1['Duration_Min']=(df1["End"]-df1["Start"]).dt.total_seconds().div(60)
我得到的是:
Process Duration_Min difference Start End
0 PROD 1055.200000 0 days 2022-06-07 06:24:48 2022-06-08 00:00:00
0 PROD -593.000000 0 days 2022-06-08 00:00:00 2022-06-07 14:07:00
1 VORG 562.733333 1 days 2022-06-07 14:37:16 2022-06-08 00:00:00
1 VORG 171.350000 1 days 2022-06-08 00:00:00 2022-06-08 02:51:21
2 STO 959.016667 2 days 2022-06-07 08:00:59 2022-06-08 00:00:00
2 STO 1440.000000 2 days 2022-06-08 00:00:00 2022-06-09 00:00:00
2 STO 1440.000000 2 days 2022-06-09 00:00:00 2022-06-10 00:00:00
2 STO -641.433333 2 days 2022-06-10 00:00:00 2022-06-09 13:18:34
我想削減事件,以便在Start
和End
之間的日期變化時創建具有新間隔的新時間戳。 如果日期之間的差異是0 days
,我不需要創建新的時間戳,並且Timedelta(days=1)
的End
時間戳不匹配。 Days
列應與weekday()
對應
我想要的是:
Start End Process Duration_Min Days
0 2022-06-07 06:24:48 2022-06-07 14:07:00 PROD 462.200000 1
1 2022-06-07 14:37:16 2022-06-07 23:59:59 VORG 562.716667 1
2 2022-06-08 00:00:00 2022-06-08 02:51:21 VORG 171.350000 2
3 2022-06-07 08:00:59 2022-06-07 23:59:59 STO 959.000000 1
4 2022-06-08 00:00:00 2022-06-08 23:59:59 STO 1439.983333 2
5 2022-06-09 00:00:00 2022-06-09 13:18:34 STO 798.566667 3
我怎么能做到這一點?
你可以試試:
def find_interval(row):
start, end = row.at["Start"], row.at["End"]
days = pd.date_range(start, end, freq="D", normalize=True).to_list()
if len(days) == 1 or days[-1] != end:
days.append(end)
days[0] = start
return list(zip(days, days[1:]))
result = (
df
.assign(Days=df.apply(find_interval, axis=1))
.explode("Days")
.assign(
Start=lambda df: df["Days"].str[0],
End=lambda df: df["Days"].str[1],
Duration_Min=lambda df:
(df["End"] - df["Start"]).dt.total_seconds().div(60),
Days=lambda df: df.groupby("Process").transform("cumcount") + 1
)
)
您的df
結果:
Start End Process Duration_Min Days
0 2022-06-07 06:24:48 2022-06-07 14:07:00 PROD 462.200000 1
1 2022-06-07 14:37:16 2022-06-08 00:00:00 VORG 562.733333 1
1 2022-06-08 00:00:00 2022-06-08 02:51:21 VORG 171.350000 2
2 2022-06-07 08:00:59 2022-06-08 00:00:00 STO 959.016667 1
2 2022-06-08 00:00:00 2022-06-09 00:00:00 STO 1440.000000 2
2 2022-06-09 00:00:00 2022-06-09 13:18:34 STO 798.566667 3
如果如評論中所示, df
的大部分不需要日間分隔,那么以下可能會更好:
m = df["Start"].dt.date < df["End"].dt.date
result = (
df[m]
.assign(Days=df.apply(find_interval, axis=1))
... <see above> ...
)
result = pd.concat([df[~m].assign(Days=1), result]).sort_index()
.sort_index()
部分是為了確保Process
-order 與df
中的相同。 刪除它,如果這不重要的話。
好的,所以您要做的第一件事是有一個日期列:
df["date"]=df[["Start","End"]].min(axis=1).dt.date
一旦你有了它,你現在需要根據你的相關列進行分組
df = df.groupby(["date",
"Process"]).agg({"Start":"min","End":"min","Duration_Min":"sum", "Days":"any"}).reset_index()
你最終應該得到相關的 dataframe
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.