我有一個熊貓資料框,如下所示。列是日期、顏色、時間和持續時間(以秒為單位)。我需要計算一天中顯示顏色的時間。
date color start time duration(seconds)
2021-07-06 RED 11:00:00.00 5
2021-07-06 RED 11:00:00.00 9
2021-07-06 BLUE 11:00:00.00 3
2021-07-06 RED 11:00:00.00 3
2021-07-06 BLUE 12:00:00.00 10
2021-07-06 BLUE 12:00:00.00 7
2021-07-06 RED 12:00:00.00 9
2021-07-06 BLUE 12:00:00.00 5
2021-07-06 RED 12:00:00.00 1
2021-07-06 RED 12:00:00.00 2
例如,在一天 24 小時內,我需要了解我們顯示顏色的時間。每天會有不同數量的顏色、交錯的開始時間和不同的持續時間。
如果我們在上面的示例中查看紅色,則顯示紅色的持續時間將為18 秒。我們不會重復計算任何顯示重疊。
我想要的輸出是一個 DataFrame,它告訴我每種顏色的顯示時間以及所有顏色的顯示時間。每種顏色或任何顏色的最長時間只能是 24 小時。對于上面的例子,答案是:
紅色持續時間:18 秒
藍色持續時間:13 秒
總持續時間:19 秒
我該怎么做呢?
uj5u.com熱心網友回復:
資料中的每一行都對應一個區間。對于任何顏色,一個時間點有多少個區間重疊是一個階躍函式。一個名為 staircase 的包建立在 pandas 和 numpy 的基礎上,用于使用 step 函式進行分析。
設定
我將使用不同的資料,以強調這種方法適用于交錯的開始時間(您的示例沒有)。我還結合日期和開始時間來簡化
df = pd.DataFrame(
{
"color":["RED", "RED","BLUE","RED","BLUE","BLUE","RED","BLUE","RED","RED"],
"start":[
pd.Timestamp("2021-07-06 11:00:00"),
pd.Timestamp("2021-07-06 11:00:02"),
pd.Timestamp("2021-07-06 11:00:01"),
pd.Timestamp("2021-07-06 11:00:04"),
pd.Timestamp("2021-07-06 11:00:05"),
pd.Timestamp("2021-07-06 11:00:05"),
pd.Timestamp("2021-07-06 11:00:08"),
pd.Timestamp("2021-07-06 11:00:07"),
pd.Timestamp("2021-07-06 11:00:12"),
pd.Timestamp("2021-07-06 11:00:14"),
],
"duration":[5,4,7,3,4,6,4,7,2,3]
}
)
df["end"] = df["start"] pd.to_timedelta(df["duration"], "s")
解決方案
我們將為每種顏色創建一個階躍函式。階躍函式由staircase.Stairs class表示。這個類是樓梯,就像系列是熊貓一樣。為此,我們將這個變數上的資料幀分組,并將子資料幀傳遞給
由于您不想計算重疊,我們需要將每個 step 函式轉換為布林值 1 - 即如果它不是零,則將其設定為 1。
stepfunctions = stepfunctions.apply(sc.Stairs.make_boolean)
現在再次繪制 RED 的階躍函式給我們

您想要做的是創建垃圾箱并集成(找到下方的區域)這些步驟功能。對于階躍函式 sf 這意味著以下計算。假設您的垃圾箱是 5 秒垃圾箱(而不是每天),只是為了讓它有趣
bins = pd.date_range(pd.Timestamp("2021-07-06 11:00:00"), freq = "5s", periods=4)
bin_sums = stepfunctions.apply(lambda sf: sf.slice(bins).integral())
這為您提供了一個按顏色索引的資料框,每個 bin 都有列。我們會融化它以更好地展示它
bin_sums.melt(var_name="bin", ignore_index=False)
color bin value
BLUE [2021-07-06 11:00:00, 2021-07-06 11:00:05) 0 days 00:00:04
RED [2021-07-06 11:00:00, 2021-07-06 11:00:05) 0 days 00:00:05
TOTAL [2021-07-06 11:00:00, 2021-07-06 11:00:05) 0 days 00:00:05
BLUE [2021-07-06 11:00:05, 2021-07-06 11:00:10) 0 days 00:00:05
RED [2021-07-06 11:00:05, 2021-07-06 11:00:10) 0 days 00:00:04
TOTAL [2021-07-06 11:00:05, 2021-07-06 11:00:10) 0 days 00:00:05
BLUE [2021-07-06 11:00:10, 2021-07-06 11:00:15) 0 days 00:00:04
RED [2021-07-06 11:00:10, 2021-07-06 11:00:15) 0 days 00:00:05
TOTAL [2021-07-06 11:00:10, 2021-07-06 11:00:15) 0 days 00:00:05
所以這種做法
- 處理重疊
- 處理跨越 bin 邊界的區間
uj5u.com熱心網友回復:
有一種解決方案,類似于staircase涉及區間陣列而不是階躍函式的解決方案。它使用一個包piso,該包是為帶有 Pandas 間隔類的集合操作而構建的
設定
假設與staircase解決方案相同的設定
解決方案
對于每種顏色創建pandas.arrays.IntervalArrays(或pandas.IntervalIndex)
import piso
interval_arrays = df.groupby("color").apply(lambda d: pd.arrays.IntervalArray.from_arrays(d["start"], d["end"]))
interval_arrays 看起來像這樣
color
BLUE [(2021-07-06 11:00:01, 2021-07-06 11:00:08], (...
RED [(2021-07-06 11:00:00, 2021-07-06 11:00:05], (...
dtype: object
我們需要在每個陣列中創建這些區間的并集
interval_arrays = interval_arrays.apply(piso.union)
然后我們創建這兩個陣列的并集以獲得總數
interval_arrays["TOTAL"] = piso.union(*interval_arrays)
interval_arrays 看起來像這樣
color
BLUE [(2021-07-06 11:00:01, 2021-07-06 11:00:08], (...
RED [(2021-07-06 11:00:00, 2021-07-06 11:00:05], (...
TOTAL [(2021-07-06 11:00:00, 2021-07-06 11:00:17]]
dtype: object
創建垃圾箱作為 pandas.IntervalIndex
bins = pd.date_range(pd.Timestamp("2021-07-06 11:00:00"), freq = "5s", periods=4)
ii_bins = pd.IntervalIndex.from_breaks(bins)
然后使用piso.coverage()它接受一個區間陣列和一個域,并回傳陣列中的區間覆寫的域(即 bin)的分數。如果我們將分數乘以 bin 大小,那么它將是總時間
interval_arrays.apply(lambda ia: pd.Series([piso.coverage(ia, bin)*bin.length for bin in ii_bins]))
這導致資料幀
color 0 1 2
BLUE 0 days 00:00:04 0 days 00:00:05 0 days 00:00:04
RED 0 days 00:00:05 0 days 00:00:04 0 days 00:00:05
TOTAL 0 days 00:00:05 0 days 00:00:05 0 days 00:00:05
列是 bin 索引。ii_bins如果需要,您可以將它們切換為間隔,也許可以融化資料框以獲得整潔的資料。
這種方法還處理重疊和處理跨越 bin 邊界的間隔。
uj5u.com熱心網友回復:
這達到了您想要的結果,這似乎是每種顏色按時間和日期的最大持續時間的總和:
df.groupby(["date", "color", "start_time"])["duration(seconds)"].max().groupby("color").sum()
輸出:
color
BLUE 13
RED 18
Name: duration(seconds), dtype: int64
獲取按時間分組的最大持續時間的總和:
df.groupby(["date", "start_time"])["duration(seconds)"].max().sum()
輸出:
19
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/340419.html
上一篇:架構師之路-https底層原理
下一篇:第一次迭代后回圈停止
