先定義時間區間
不等距採樣不能把每筆數值直接平均後假稱代表整段時間。先固定半開區間,例如[00:00,00:15),再說明值是瞬時讀值、區間增量或階梯保持。本文案例為階梯式量測:00:00值10、00:01值20、00:10值40,將每個讀值保持到下一次讀值或區間結束。
時間權重的核心是每個值覆蓋多少分鐘。00:00的10覆蓋1分鐘,00:01的20覆蓋9分鐘,00:10的40覆蓋5分鐘,因此加權總量為10×1+20×9+40×5=390,除以15分鐘得到26。這個26是時間加權平均,不是三筆樣本的算術平均。
若報表要求樣本平均,則(10+20+40)/3=70/3=23.333。兩者都可正確,但回答的是不同問題:樣本平均回答「收到的三次讀值平均」,時間加權平均回答「15分鐘內每分鐘暴露的階梯值平均」。欄位名稱必須把方法寫出來。
| 值 | 起點 | 下一起點/結束 | 覆蓋分鐘 | 乘積 |
|---|---|---|---|---|
| 10 | 00:00 | 00:01 | 1 | 10 |
| 20 | 00:01 | 00:10 | 9 | 180 |
| 40 | 00:10 | 00:15 | 5 | 200 |
時間加權公式可用簡單表格重算,而不必依賴特定平台:對每段取leftValue與rightBoundary,先算分鐘差,再累加value×duration。若時間單位改成秒,分子與分母都同乘60,結果仍為26;若只把分子乘60,結果就會錯。資料表應保存duration與weightedContribution,方便稽核者逐列重現。
前值 插值與缺口
前值保持適合代表「直到下一筆前仍沿用最後有效狀態」的訊號,例如離散的數值設定值;類別狀態碼可以按前值保持計算各狀態持續時間,但不能把碼號直接平均解讀成物理量;它不表示感測器在缺測期間真的量到相同值。報表應保存sourceTimestamp、acquiredAt、freshness與fillMethod,讓讀者知道40是00:10讀到的值,不是00:14重新量測。
線性插值適合在兩端有效、且工程上可接受平滑變化時使用。若00:01到00:10由20升到40,等距時間點的中間值可依比例計算;但若輸送量是階梯跳變,線性插值會製造不存在的中間狀態。方法不能只由函式名稱決定,要先看訊號語意。
pandas interpolate文件把linear視為等距索引的線性插值,time則使用時間間隔;limit可限制連續缺值數,搭配limit時,limit_area=inside只處理兩端都有值的內部缺口。這些工具參數不會替系統決定哪種聚合代表製程,仍需將方法版本與適用條件寫進報表。
| 方法 | 本例結果 | 適用解讀 | 風險 |
|---|---|---|---|
| 時間加權前值 | 26 | 階梯值覆蓋時間 | 缺測被視為保持 |
| 樣本平均 | 23.333 | 每筆觀測等權 | 忽略時間間隔 |
| 線性插值後平均 | 需明示首尾模型 | 兩端有效且可平滑 | 可能製造假中間值 |
時間加權聚合還要決定邊界值屬於哪一段。本文使用半開區間[00:00,00:15),所以00:15的讀值留給下一段,不計入本段;若改用閉區間,可能讓同一讀值在兩個報表重複。資料庫查詢、排程器與畫面標示都要採同一時區與邊界規則,並在結果中保存windowStart、windowEnd與windowConvention。
當兩個讀值時間相同,同時刻的不同更新可按可靠來源序號決定之後持有哪個值,零時長段不貢獻平均。同一識別的重送才標Duplicate;不同識別卻無法判定先後時標Conflict;不能任意用最後到達時間改變歷史。時間倒退則應拒絕進入聚合,並保存clockError原因。
若改為00:00至00:01線性10升20、00:01至00:10線性20升40,最後五分鐘仍保持40,則精確梯形面積15×1+30×9+40×5=485,平均32.333。此計算不需先選等距網格,但必須清楚交代最後一段保持;不能只寫線性平均而省略尾端假設。
公式與資料品質
實作時先把帶時區時間轉為統一UTC時間基準,另檢查來源時鐘回撥;UTC本身不保證來源時鐘單調,排序後檢查重複時間、倒退時間與超過允許間隔的缺口。對每個區間計算duration=max(0,min(nextTimestamp,end)-max(timestamp,start)),再以sum(value×duration)/sum(duration)求平均;若分母不足整段,另輸出coverage,不要用零補足。
00:00到00:15的案例若漏掉00:10資料,最後的40不存在,就不能仍宣稱26。可以保留[00:01,00:15)的20做前值保持,或把結果標成InsufficientCoverage;選擇哪一種要由方法規則決定。資料缺測、來源Bad與來源晚到要分開標記。
若值是每分鐘增量而不是狀態值,時間加權平均也要先確認單位。增量應按區間累加,不能把「件數」乘分鐘;速率才可用值乘時間得到量。報表契約加入valueKind=level、rate或increment,能避免同一套公式誤用。
晚到資料需要版本化重算。若00:10的40在00:20才送達,第一次報表可能只有10與20,第二次回補才得到完整390。兩次結果都應有runId、receivedWatermark與coverage;使用者看到26時能知道它是回補版,而不是把晚到事件改寫成原本準時收到。
前值保持的估算標誌不應與來源品質混在一欄。來源可為Good但資料在窗口內沒有新讀值,計算結果仍應是Held或Stale;來源本身為Bad時,即使最後數字存在,也不能把它當成Good的保持值。報表同時顯示sourceQuality、freshnessStatus與fillMethod,讀者才能分辨三種狀態。
驗收與排錯
驗收固定輸入三筆資料並手算:前值保持總量390、平均26;樣本總和70、樣本平均23.333。再加入00:05值30,四段權重為1、4、5、5分鐘,分子10+80+150+200=440,時間平均29.333;四筆樣本平均25。兩者仍不同。另測00:15剛好等於結束邊界,確認半開區間不重複計算下一段。
結果異常時先查時區與單位,再查是否把acquiredAt誤當sourceTimestamp。若平均偏向晚到值,檢查是否用樣本平均;若邊界多一分鐘,檢查end是否採閉區間;若缺口被填成零,檢查缺測策略與null處理。所有重算都保存快照ID與methodVersion。
本篇公式是可重算的教學案例,不代表任何PLC、SCADA或資料庫預設使用前值保持。
對狀態碼使用前值保持時,應設定最大freshness。若最後有效值20已超過15分鐘仍無新資料,結果應標為Stale而不是無限延長20。對速率或溫度等連續量,可另選線性或積分方法;方法差異要以訊號的物理意義和缺測風險決定,不能為了讓曲線平滑而隱藏不確定性。
窗口重採樣還要明定空窗如何發布。若00:00前沒有有效值,前值保持不能向前外推;若00:10後直到00:15沒有新值,只有在最大freshness允許時才沿用40,否則縮短分母並標示coverage不足。這能避免同一套程式對窗口開頭與結尾採用不對稱且未說明的補值。
做跨設備比較時,兩台設備即使都每15分鐘出一個平均,也要確認各自使用的時間邊界、時區、前值期限與late回補規則。先匯出每段的duration、有效時間與方法版本,再比較26等結果;只比較畫面上的一個數字,無法判斷差異來自製程還是聚合設定。
若使用秒級資料,保留原始時間精度,最後再依報表需要換算分鐘,避免整分鐘截斷造成權重誤差。
FAQ與來源
FAQ1:26和23.333哪個正確?兩者都可能正確,分別是時間加權平均與樣本平均,必須看報表定義。
FAQ2:前值保持等於真實量測嗎?不是,它是明示的估算或保持方法,必須保留fillMethod與品質。
FAQ3:不等距資料可直接用linear嗎?只有在索引代表等距時間且規則允許時;否則應用時間距離或明確拒絕。
FAQ4:缺測可以填零嗎?只有零本身代表已確認的製程值才可,未知資料不能默認為零。
參考:pandas DataFrame.interpolate:linear、time、limit與limit_area參數語意。
參考:pandas時間序列使用說明,供時間索引與重採樣概念查閱。
參考:RFC 3339:網際網路日期時間格式,供來源時間戳與時區欄位設計參考。