假設以下資料框架df:
import pandas as pd
data = {"Time"/span>:["2021-01-10 21:00:00", "2021-01-10 22:00:00",
"2021-01-10 21:30:01"/span>, "2021-01-10 21:45:00"/span>,
"2021-01-12 09:00:00", "2021-01-12 09:30:00"] 。
"ID"。 ["1"/span>,"1"/span>,"2"/span>, "2","2","2"】。]
"Event": ["cut","cut", "smooth", "smooth","cut","cut"】。]
"狀態"。 ["開始", "完成", "開始", "complete","start", "complete",] }
df = pd.DataFrame(data)
df["Time"] = pd.to_datetime(df["Time"] )
df["ID"] = df["ID"].astype("int")
df
我的最終目標是計算每個獨特的 "ID "的總生產時間,不考慮每個時間間隔之間任何潛在的時間間隔。每個ID的開始時間是 "開始 "狀態的第一個實體,而結束生產時間是每個ID "完成 "狀態的最后一個實體。例如,對于ID==1來說,這是1小時(3600秒),而對于ID==2來說,大約是45分鐘(第一個時間間隔為15分鐘,第二個時間間隔為30分鐘)。
由于我對捕捉每個獨特ID的時間間隔也很感興趣(例如,ID==1只有1個間隔,與它的總生產時間一致,ID==2有2對開始-完成狀態,因此有2個間隔),我想做的是創建兩個字典:'time_diff_dict'和'cumulativeSumId':
這樣,在'cumulativeSumId'字典中,每個鍵(ID)的最后一個鍵值將等于其總生產時間。
然而,想象一下,真實的df有大約180,000行,有大約3000個唯一的ID,終止下面的代碼需要大約10min。可能我將不得不使用類似于描述的迭代方法
,例如,對于ID==1,總的生產時間是3600秒,對于ID==2是2699秒,因為這是其累計總時間字典中的最后一個實體。
之后,我創建了一個新的df,其中有:唯一的ID,"totalTimeId "和 "timeIntervals":
''
*創建串列的串列
* 每一個子串列都是一個獨特的ID的資料框架
'''
lists_of_IDdfs =[]
for id, df_id in df.groupby("ID") 。
lists_of_IDdfs.append(df_id)
資料 = []
for df in range(len(lists_of_IDdfs))。
data.append((lists_of_IDdfs[df].ID.iloc[-1], lists_of_IDdfs[df].Cumulative_Time.iloc[-1])
df_ID_TotalTime = pd.DataFrame(data, columns= ["ID", "totalTimeId"] )
''為每個唯一的ID添加各自的時間區間資料點''。
df_ID_TotalTime["timeIntervals"] = df_ID_TotalTime["ID"].map(time_diff_dict)。
df_ID_TotalTime
最終期望的結果是:
如果有任何想法和幫助,我將不勝感激! 謝謝你!
uj5u.com熱心網友回復:
你可以使用pivot重塑你的資料框架,計算兩個日期之間的差異,并使用groupby"ID "來聚合資料:
# pre-requisite ensure that Time is of datetime type<
df['Time'] = pd.to_datetime(df['Time'] )
(df.pivot(index=['ID', 'Event'], columns='Status', values='Time')
.assign(time=lambda d: d['complete']-d['start'] )
.groupby('ID')['time'].sum()
)
輸出:
ID
1 0天 00:30: 00
2 0天 00:24:58
要獲得以秒為單位的輸出:
(df. pivot(index=['ID', 'Event'], columns='Status', values='Time')
.assign(time=lambda d: d['complete']-d['start'] )
.groupby('ID')['time'].sum()
.dt.total_seconds()
)
輸出:
ID
1 1800.0
2 1498.0
另一種輸出方式:
(df. pivot(index=['ID', 'Event'], columns='Status', values='Time')
.assign(time=lambda d: (d['complete']-d['start']) dt.total_seconds()
.groupby('ID')['time'].agg(totalTimeId='sum',timeIntervals=list)
)
輸出:
totalTimeId timeIntervals
編碼
1 3600.0 [3600.0]
2 2699.0 [1800.0,899.0]
編輯如何處理重復的內容:
你需要添加一個唯一的二級索引(ID2)
(df.assign(ID2=df.groupby(['ID'/span>, 'Event'/span>, 'Status'/span>]) .cumcount()
.pivot(index=['ID', 'ID2', 'Event'], columns='Status', values='Time')
.assign(time=lambda d: (d['complete']-d['start']) dt.total_seconds()
.groupby('ID')['time'].agg(totalTimeId='sum',timeIntervals=list)
)
輸入:
時間 ID 事件 狀態
0 2021-01-10 21: 00:00 1 切割開始
1 2021-01-10 22: 00:00 1 切割完畢
2 2021-01-10 21:30: 01 2順利開始
3 2021-01-10 21: 45:00 2順利完成
4 2021-12 09:00:00 2 切割開始
5 2021-12 09:30:00 2 切割完成
6 2021-12 09:30:00 2 切割開始
7 2021-01-12 09:35:00 2 切割完成
中級:
Status complete start
ID ID2 事件
1 0 cut 2021-01-10 22:00: 00 2021-01-10 21:00:00
2 0 cut 2021-01-12 09:30: 00 2021-01-12 09:00:00
順利2021-01-10 21:45。 00 2021-01-10 21:30:01
1 cut 2021-01-12 09:35: 00 2021-01-12 09:30: 00
輸出:
totalTimeId timeIntervals
編碼
1 3600.0 [3600.0]
2 2999.0 [1800.0,899.0,300.0]
uj5u.com熱心網友回復:
你可以按ID進行分組,然后計算出定時器:
df['Cumulative_Time'] = df. groupby('ID')['Time'].apply(lambda x: x - x.min() .dt.total_seconds()
為了得到你想要的輸出,你可以做以下事情,靈感來自@mozway的回答。
(df.groupby(['ID','Event']) ['Time']
.apply(lambda x: x.max() - x.min() .dt.total_seconds()
.groupby('ID')
.agg(totalTimeId='sum', timeIntervals=list)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/309436.html
標籤:
上一篇:如何有效地更新多維陣列的多個副本


