先保留量測狀態 再決定數值能不能用
流量為 0,可能是閥門關閉後的正常量測;流量欄位空白,可能是資料還沒到,也可能是匯出漏欄。如果一律補成 0,報表雖然能算,意思卻已經改了。這篇帶你建立一份小型資料契約:數值欄只放可解讀的量測,品質欄負責說明它能不能用,錯誤碼則留下排查線索。
先把「CSV 語法」和「資料意義」分開。CSV 解決欄位如何分隔、文字如何加引號;它不會替你的工廠定義空白等於零、NULL 等於未到達,或 -9999 等於感測器故障。這些意義必須由匯出端、匯入端與報表一起約定。以下 quality 名稱與案例都是本文的教學設計,不是 PLC 或通訊協定的內建標準。
| 狀態 | flow 欄內容 | quality | 統計處理 |
|---|---|---|---|
| 有效零流量 | 0 | GOOD | 納入平均及有效筆數 |
| 預期資料尚未到達 | 空欄 | PENDING | 不當零;計入待到筆數 |
| 來源明確回報錯誤 | 空欄 | ERROR | 不納入量測平均;保留錯誤碼 |
| 匯入欄位缺失或空白 | 空欄 | MISSING | 列入缺漏,追查匯出或填寫流程 |
若整筆資料尚未到達,系統可能根本沒有這一列。要在報表顯示 PENDING,還需要預先知道應到時間與測點清單,再由收集端建立待到紀錄。不要把每個不存在的資料列都自行補成正常零值。
把欄位字典寫到能讓另一個人照做
本例以每分鐘一筆的虛構流量資料練習。欄位 timestamp 表示預期或實際量測時刻,station 為測點識別碼,flow 的工程單位固定為 L/min,quality 表示品質,error_code 記錄來源錯誤。時間究竟代表量測還是收集,必須選定並寫明;若兩者都需要,就用兩個欄位,不能在同一欄輪流放。
| 欄位 | 型別與約定 | 檢查方式 |
|---|---|---|
| timestamp | 含時區的時間文字;本例為量測槽時間 | 格式與時區固定,不用電腦地區設定猜 |
| station | 文字識別碼 | 空白拒收;前導零保留 |
| flow | 十進位數值或空欄;單位 L/min | GOOD 必須可解析且符合合理範圍 |
| quality | GOOD/PENDING/ERROR/MISSING | 未知代碼拒絕自動納入統計 |
| error_code | 文字;無錯誤時為空欄 | ERROR 必須附可追查代碼或原因 |
再加兩條一致性規則:GOOD 配空欄不能通過;ERROR 配一個數字,也不能直接當有效量測。後者可能是設備保留的上一筆值。若你要顯示最後有效值,另外記 last_good_value 與 last_good_time,並標示目前品質,不能讓舊值冒充這次的新量測。
不要在 flow 裡混用「無資料」「錯誤」「--」和數字,迫使每份報表猜字串。若舊系統已用 -9999 當錯誤值,轉換時先核對原廠定義,把它轉到品質欄,並保留原始檔。不能因數字看起來不合理就自行認定它是錯誤碼。
用四列資料練習匯出與讀回
下面四列為合成資料,沒有連接 PLC。欄名依序為 timestamp、station、flow、quality、error_code。連續兩個逗號表示中間欄位為空;最後一個逗號後是空的 error_code 欄。每列仍有五個欄位。
timestamp,station,flow,quality,error_code
2026-09-17T09:00:00+08:00,F01,0,GOOD,
2026-09-17T09:01:00+08:00,F01,,PENDING,
2026-09-17T09:02:00+08:00,F01,,ERROR,E_TIMEOUT
2026-09-17T09:03:00+08:00,F01,,MISSING。
用文字編輯器檢查原始內容,確認五欄與四筆資料;不要先在試算表覆存。
以明確分隔符號和編碼匯入;station、quality、error_code 保持文字。先檢查空欄,再對 flow 做受控數值轉換。
逐列執行字典規則。第一列保留數字 0;其他三列保留其狀態,不補 0。
再匯出到新檔,以 CSV 解析器讀回,比較欄位值與狀態;引號和換行格式可能不同,但解讀後的資料應一致。
常見失敗是只比畫面:空欄和數值零在某些顯示設定下都看起來空白,實際型別卻不同。比較時要分別檢查數值是否為 0、是否缺值,以及 quality 的文字;不能用「儲存格看起來沒東西」作為驗收。
平均值必須連同有效筆數一起交代
這四列只有一筆 GOOD,因此有效平均流量為 0 L/min,有效筆數為 1,預期筆數為 4,有效資料比例為 25%。這個結果不能解讀成四分鐘都正常零流量。若沒有任何 GOOD 資料,平均值應呈現「無有效資料」,不能用 0 取代未定義的平均。
| 報表項目 | 本例結果 | 代表意義 |
|---|---|---|
| 有效平均 | 0 L/min | 只由第一列計算 |
| 有效資料 | 1/4 = 25% | 分母為事先預期四筆 |
| 待到/錯誤/缺漏 | 各 1 筆 | 三種不同的處理責任 |
| 零值筆數 | 1 筆 | 只計 GOOD 且 flow=0 |
再加一筆 GOOD=12 作為延伸練習。兩筆有效值的平均是 (0+12)÷2=6;若把三筆異常全補成 0,算出的 12÷5=2.4 就是被缺值拉低的結果。這兩個數字差異來自聚合規則,不是感測器倍率。資料不是等時間間隔時,簡單平均也不能直接當時間加權平均,更不能把瞬時流量直接相加當累計體積。
趨勢圖遇到 ERROR 應依規格斷線或標記,不要未說明就把缺口平滑連起來。若採用補值,須保留原品質、補值方法與補值旗標,讓讀者分得出量測與估算。品質資訊和數值一起傳遞,才不會在下一份報表又失去意義。
完成結果與失敗排查
| 看到的現象 | 先查哪裡 |
|---|---|
| 四種狀態都變成 0 | 匯入缺值替換、數值轉換與報表公式 |
| NULL 被當一般文字 | 雙方是否明訂 NULL 字串為缺值標記 |
| GOOD 卻沒有數值 | 匯出時漏值或品質狀態不同步 |
| 讀回少一欄 | 分隔符、引號、欄數與尾端空欄解析 |
| 平均為空或報錯 | 是否沒有 GOOD 資料;是否混入錯誤字串 |
完成後,四列資料應仍可區分正常零、待到、來源錯誤與缺漏;有效計數為 1,平均為 0,品質分布各一筆。延伸案例的有效平均應為 6。你要驗收的是「意義未變」,不是只確認 CSV 可以開啟。
常見問題
空欄和雙引號空字串可以表示不同意思嗎?某些工具提供區別機制,但不能假設所有 CSV 匯入端都保留差異。本例使用 quality 明確區分,因此不依賴引號是否存在。
CSV 裡寫 NULL 就會自動變缺值嗎?不會保證。先在資料契約定義,再核對匯入器;否則它只是四個字母。
把 None 匯出再讀回一定可還原嗎?Python 一般 csv.writer 會將 None 寫為空字串,官方指出這種轉換不可逆;不同引用模式另有行為。若需要原意,請另存品質欄,而不是依賴預設。
適用型號與限制:本文適用於 CSV 資料交換設計,沒有指定三菱 SD 卡指令或任何 HMI 匯出格式。實際欄名、編碼、可空型別與寫入方式須核對目標平台。
參考:RFC 4180 第 2 節 CSV 格式;此文件為 Informational,不定義工業品質代碼
參考:Python 3 csv 文件 writer 與引用模式;None 的預設轉換
參考:Microsoft Power Query Text/CSV connector 匯入設定與型別偵測