我有以下資料集:
date event next_event duration_Minutes
2021-09-09 22: 30: 00 1 2021 09-09 23: 00: 00 30
2021-09-09 23:00。 00 2 2021 09-09 23: 10: 00 10
2021-09-09 23: 10: 00 1 2021 09-09 23: 50: 00 40
2021-09-09 23:50。 00 4 2021-09-10 00: 50:00 60: 60
2021-09-10 00: 50: 00 4 2021-09-12 00: 50: 00 2880
主要的問題是,我想以如下方式將多天的事件分成獨立的事件。我想讓事件的持續時間從2021-09-09 23:50:00到2021-09-10 00: 00: 00,然后是2021-09-10 00: 00: 00到2021-09-10 00:50:00,以此類推。這將是有用的,因為之后,我需要按日分組事件,并按日計算每個事件的持續時間,所以我想解決這些事件之間存在日期變化的情況。
我想得到這樣的結果:
date event next_event duration_Minutes
2021-09-09 22: 30: 00 1 2021 09-09 23: 00: 00 30
2021-09-09 23:00。 00 2 2021 09-09 23: 10: 00 10
2021-09-09 23: 10: 00 1 2021 09-09 23: 50: 00 40
2021-09-09 23:50。 00 4 2021-09-10 00: 00:00 10: 10
2021-09-09 00:00。 00 4 2021-09-10 00: 50: 00 50
2021-09-10 00:50。 00 4 2021-09-11 00: 00:00 1390
2021-09-11 00:00: 00 4 2021-09-12 00: 00:00 1440
2021-09-12 00:00。 00 4 2021-09-12 00: 50: 00 50
它應該能夠處理我們在一整天或更長時間內沒有事件的情況,就像例子中那樣。
我現在的解決方案是:
我現在的解決方案是:
first_record_hour_ts = df.index.floor('H') [0]
last_record_hour_ts = df.index.floor('H') [-1]
# 創建一個從第一個到最后一個包含Nan的日期的系列。
df_to_join = pd.Series(np.nan, index=pd.date_range(first_record_hour_ts, last_record_hour_ts, freq='H'/span>)
df_to_join = pd.DataFrame(df_to_join)
# Concatenate with current status dataframe[/span]。
df = pd.concat([df, df_to_join[~df_to_join.index.isin(df.index)]).sort_index()
# Forward fill the nana[/span]。
df.fillna(method='fill', inplace=True)
df['next_event'] = df.index.shift(-1)
# 計算兩個狀態之間的delta。
df['duration'/span>] = df['next_event'/span>] - df.index
# 轉換成分鐘。
df['duration_Minutes'] = df['duration_Minutes'].apply(lambda x: x.total_seconds() // 60)
這并沒有完全解決這個問題,但我認為它可能會解決我的目標,即在最后能夠按事件和按日期分組。
uj5u.com熱心網友回復:
好吧,下面的代碼看起來有點長 -- 而且肯定有更好/更有效/更短的方法來做這個。但我認為它是相當簡單的,可以跟上。
split_datetime_span_by_day下面需要兩個日期。start_date和end_date。在你的例子中,它將是你的源資料中的date和next_event。
然后該函式檢查該時間段(start -> end)是否跨越了午夜。如果不是,它將回傳開始日期、結束日期和以秒為單位的時間段。如果它跨越了午夜,它將創建一個新的分段(start -> midnight),然后再次呼叫自己(即遞回),這個程序一直持續到該時間段沒有跨越午夜為止。
只需注意:回傳的片段串列是由(start, end, nmb_seconds)的圖元組成的。我回傳的是秒數,而不是你問題中的分鐘數,因為我不知道你想如何對秒數進行四舍五入(向上、向下等)。這是給讀者的一個練習:-)
。
from datetime import datetime, timedelta
def split_datetime_span_by_day(start_date, end_date, split_segments=None) 。
assert start_date < end_date # sanity check。
# when is the next midnight after start_date?
# adapted from https://ispycode.com/Blog/python/2016-07/Get-Midnight-Today
start_next_midnight = datetime.combe(start_date, datetime.min.time() timedelta( days=1)
if split_segments is None。
split_segments = []
if end_date < start_next_midnight:
# end date is before next midnight, no split necessary。
return split_segments [(
start_date,
end_date,
(end_date - start_date).total_seconds()
)]
# otherwise, split at next midnight...
split_segments = [(
start_date,
start_next_midnight,
(start_next_midnight - start_date).total_seconds()
)]
if(end_date - start_next_midnight).total_seconds() > 0。
# ...and recurse to get next segment.
return split_datetime_span_by_day(
start_date=start_next_midnight,
end_date=end_date。
split_segments=split_segments
)
else:
# case where start_next_midnight == end_date i.e. end_date is midnight。
# don't split & create a 0 second segment。
return split_segments
# 測驗案例。
start_date = datetime.strptime('2021-09-12 00:00:00', '%Y-%m-%d %H:%M:%S')
end_date = datetime.strptime('2021-09-14 01:00:00', '%Y-%m-%d %H:%M:%S')
print(split_datetime_span_by_day(start_date=start_date, end_date=end_date) )
# returned values:(回傳值)。
# []。
# (datetime.datetime(2021, 9, 12, 0, 0), datetime.datetime(2021, 9, 13, 0, 0), 86400.0) ,
# (datetime.datetime(2021, 9, 13, 0, 0), datetime.datetime(2021, 9, 14, 0, 0), 86400.0) ,
# (datetime.datetime(2021, 9, 14, 0, 0), datetime.datetime(2021, 9, 14, 1, 0), 3600.0)
# ]
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/312011.html
標籤:
