返回文章列表

時序資料處理:Pandas 技巧與缺失值填補策略

本文探討如何使用 Pandas 處理時序資料中的缺失值,涵蓋日期時間轉換、本地化、重取樣、插值等技巧。以芝加哥智慧綠色基礎設施監測感測器資料集為例,示範如何填補缺失的感測器資料,並避免常見錯誤。文章重點分析不同聚合函式對缺失值的影響,並提供程式碼範例和技術選型建議,幫助讀者提升時序資料處理能力。

資料分析 Python

在時序資料分析中,缺失值處理是不可或缺的環節。本文以芝加哥智慧綠色基礎設施感測器資料為例,示範如何使用 Pandas 處理時序資料,特別是針對缺失值的填補和重構。首先,我們將原始資料的「Measurement Time」欄位轉換為日期時間格式,並設定正確的時區。接著,針對特定感測器資料進行篩選和重取樣,觀察缺失值對不同聚合函式(如平均值和總和)的影響。 Pandas 的 interpolate 函式是填補缺失值的利器,可以根據前後資料進行插值。然而,直接使用 interpolate 之前,需要先進行分鐘級重取樣,確保每分鐘都有資料點,並設定 min_count 引數避免預設將缺失值視為 0。最後,透過視覺化驗證處理後的資料,確保每小時都有 60 個事件,並檢視每日總和的變化趨勢。

資料分析中的時序資料處理

資料分析中,時間序列資料是一種非常重要的資料形式,特別是當涉及到大量交易或感測器資料時,這些資料可能會出現缺失值。缺失值會對資料分析產生重大影響,可能導致資料不完整或錯誤。因此,準確衡量並適當補齊這些缺失的交易是至關重要的。

舉例分析:智慧綠色基礎設施監測感測器

在這篇文章中,玄貓將使用芝加哥市提供的「智慧綠色基礎設施監測感測器 - 歷史資料集」,這個資料集包含了芝加哥市內不同環境因素的感測器資料,如水流量和溫度。理論上,這些感測器應該持續執行並報告數值,但實際上,它們容易出現間歇性故障,導致資料丟失。

如何操作

芝加哥市資料門戶提供的原始資料以 CSV 格式儲存,範圍為 2017 和 2018 年。然而,為了本次分析,我們將使用一個經過精選的 Parquet 檔案,僅涵蓋 2017 年 6 月到 10 月的資料。這些資料包含了近五百萬條記錄,我們可以使用 pd.read_parquet 語法快速載入:

import pandas as pd

df = pd.read_parquet(
    "data/sgi_monitoring.parquet",
    dtype_backend="numpy_nullable",
)
df.head()

觀察初步結果

Measurement Title Measurement Description Measurement Type ... Latitude Longitude Location
0 UI Labs Bioswale NWS Proba-bility of Precipi-tation <NA> TimeWin-dowBounda-ry ... 41.90715 -87.653996 POINT (-87.653996 41.90715)
1 UI Labs Bioswale NWS Proba-bility of Precipi-tation <NA> TimeWin-dowBounda-ry ... 41.90715 -87.653996 POINT (-87.653996 41.90715)
2 UI Labs Bioswale NWS Proba-bility of Precipi-tation <NA> TimeWin-dowBounda-ry ... 41.90715 -87.653996 POINT (-87.653996 41.90715)
3 UI Labs Bioswale NWS Proba-bility of Precipi-tation <NA> TimeWin-dowBounda-ry ... 41.90715 -87.653996 POINT (-87.653996 41.90715)
4 UI Labs Bioswale NWS Proba-bility of Precipi-tation <NA> TimeWin-dowBounda-ry ... 41.90715 -87.653996 POINT (-87.653996 41.90715)

從上述結果可以看出,「Measurement Time」欄位應該包含每個事件發生的時間戳記,但仔細檢查後發現 Pandas 沒有識別這些值為日期時間格式:

df["Measurement Time"].head()
0    07/26/2017 07:00:00 AM
1    06/23/2017 07:00:00 AM
2    06/04/2017 07:00:00 AM
3    09/19/2017 07:00:00 AM
4    06/07/2017 07:00:00 AM
Name: Measurement Time, dtype: string

轉換為日期時間格式

首先需要將這些值轉換為真正的日期時間格式。根據芝加哥市資料門戶的檔案,這些時間戳記是當地時間(美國中部時區),我們可以使用 pd.Series.dt.tz_localize 處理:

df["Measurement Time"] = pd.to_datetime(
    df["Measurement Time"]
).dt.tz_localize("US/Central")

轉換後的結果如下:

df["Measurement Time"].head()
2   2017-06-23 22:48:32-05:00
3   2017-12-31 23:58:48-06:0...
...
4   2...-...
dtype: datetime64[ns, US/Central]

檢查感測器型別與單位

接下來檢查 Measurement TypeUnits 欄位,瞭解我們正在處理的資料:

df[["Measurement Type", "Units"]].value_counts()

結果顯示各種不同型別的感測器及其單位:

Temperature          degrees Celsius      ...
DifferentialPressure pascals                ...
WindSpeed            meters per second     ...
Temperature         millivolts             ...
SoilMoisture        millivolts             ...
RelativeHumidity      percent              ...
CumulativePrecipitation count              ...
WindDirection     degrees from north      ...
SoilMoisture Percent Volumetric Water Content ...
CumulativePrecipitation inches             ...
TimeWindowBoundary universal coordinated time ..

資料篩選與重樣

由於不同感測器產生不同型別的測量數值,我們需要小心地避免同時比較多個感測器。本次分析將專注於 TM1 溫度感測器(Temperatures in millivolts)。此外,我們還需要篩選特定的 Data Stream ID:

mask = (
    (df["Measurement Description"] == "TM1 Temp Sensor")
    & (df["Data Stream ID"] == 39176)
)
df = df[mask].set_index("Measurement Time").sort_index()

篩選後的結果如下:

df[["Measurement Type", "Units"]].value_counts()
Temperature     millivolts     ...
Name: count, dtype: int64

接下來我們開始對 Measurement Value 欄位進行日級別重樣並使用均值聚合:

df.resample("D")["Measurement Value"].mean().plot()

分析缺失值影響

從圖表中可以清楚看到兩個主要空缺區域:一個在七月底和另一個在十月中旬。這些空缺幾乎肯定是由於感測器故障導致。

我們可以進一步縮小日期範圍以更清楚地檢視哪些天缺失了記錄:

df.loc["2017-07-24":"2017-08-01"].resample("D")["Measurement Value"].mean()
...
2   ...<NA>
dtype: Float64....

#### 內容解密:

轉換日期時間格式

玄貓首先使用了 pd.to_datetime 函式將「Measurement Time」欄位中的字串轉換為日期時間格式。接著利用 dt.tz_localize 函式將其本地化為美國中部時區(US/Central),這樣才能夠進行準確的時序分析。

檢查感測器型別與單位

透過檢查「Measurement Type」和「Units」欄位,玄貓瞭解到這個資料集包含多種不同型別的感測器和測量單位。這一步對於後續的資料處理和分析非常重要,因為不同型別的感測器需要不同的處理方法。

資料篩選與重樣

玄貓選擇專注於「TM1 Temp Sensor」,並篩選出特定的 Data Stream ID(39176)。然後將「Measurement Time」設為索引並排序。接著進行日級別重樣並使用均值聚合以便更高層次地理解資料。

分析缺失值影響

透過繪製重樣後的平均值圖表,玄貓發現了兩個明顯的空缺區域:七月底和十月中旬。這些空缺區域可能是由於感測器故障導致。進一步縮小日期範圍進行檢視則更加清楚地顯示了哪些天缺失了記錄。

時序資料處理:填補缺失值與重構資料

在時間序列資料分析中,缺失值是常見的問題。這些缺失值可能會導致資料分析結果不準確,甚至誤導決策。玄貓將詳細探討如何使用Pandas來處理時間序列資料中的缺失值,並展示具體的案例和技術選型分析。

缺失值的影響與處理

首先,觀察原始資料可以發現,2017年7月31日的資料完全缺失。這種情況會導致資料視覺化中出現明顯的間隙。為瞭解決這個問題,可以使用Pandas的pd.Series.interpolate方法來填補缺失值。這個方法會根據前後的資料進行插值,從而消除間隙。

df.resample("D")["Measurement Value"].mean().interpolate().plot()

內容解密:

  • 程式碼解說:此段程式碼首先對DataFrame df進行重取樣(resample),以天為單位計算「Measurement Value」的平均值,然後使用interpolate()方法填補缺失值,最後繪製圖表。
  • 設計考量:這樣的處理方式適合於資料中的間隙不會顯著影響平均值計算的情況。
  • 技術原理:插值(interpolation)是一種數學方法,用於估計兩個已知資料點之間的未知值。
  • 潛在改進點:如果資料中的缺失值較多且持續時間較長,可以考慮使用其他插值方法(如線性插值、樣條插值等)來提高準確性。

不同聚合函式對缺失值的影響

不同的聚合函式對缺失值的處理方式不同。例如,計算平均值時,缺失的交易可能被平均掩蓋,不會顯著影響結果。然而,如果要計算每日總和,情況就不同了。

df.resample("D")["Measurement Value"].sum().plot()

內容解密:

  • 程式碼解說:此段程式碼對DataFrame df進行重取樣,以天為單位計算「Measurement Value」的總和,然後繪製圖表。
  • 設計考量:總和運算對缺失值非常敏感,一個缺失的交易可能會顯著影響總和結果。
  • 技術原理:總和運算直接累加所有非空值,因此對於完整性要求較高。
  • 潛在改進點:在計算總和之前,應該先檢查並處理缺失值。

確認感測器故障期間

透過深入分析資料,發現7月30日至8月1日的感測器故障期間實際上持續了近兩天。這種情況在計算平均值時可能被掩蓋,但在計算總和時會顯得更為明顯。

df.loc["2017-07-30 15:45:00":"2017-08-01"].head()

內容解密:

  • 程式碼解說:此段程式碼選取2017年7月30日至8月1日的資料並顯示前五行。
  • 設計考量:這樣的操作有助於確認感測器故障期間及其持續時間。
  • 技術原理:透過定位具體時間範圍內的資料,可以快速識別異常情況。
  • 潛在改進點:可以增加自動檢測感測器故障的機制,減少手動檢查的工作量。

重新取樣與插補

為了確保每分鐘都有資料點,可以對資料進行分鐘級重取樣並使用插補方法來填補缺失值。

df.resample("min")["Measurement Value"].sum().interpolate()

內容解密:

  • 程式碼解說:此段程式碼對DataFrame df進行分鐘級重取樣,計算「Measurement Value」的總和並使用插補方法填補缺失值。
  • 設計考量:這樣的處理方式有助於確保每分鐘都有完整的資料點。
  • 技術原理:插補方法根據前後資料點進行估計,從而填補缺失值。
  • 潛在改進點:可以根據具體需求選擇不同的插補方法(如線性插補、樣條插補等)。

避免預設處理方法

預設情況下,Pandas會將所有缺失值視為0進行累加。為了避免這種情況,可以使用min_count引數來設定最小非空值計數。

interpolated = df.resample("min")["Measurement Value"].sum(min_count=1).interpolate()

內容解密:

  • 程式碼解說:此段程式碼對DataFrame df進行分鐘級重取樣,設定最小非空值計數為1並使用插補方法填補缺失值。
  • 設計考量:這樣的處理方式可以避免預設將所有缺失值視為0進行累加。
  • 技術原理min_count引數用於設定最小非空值計數條件。
  • 潛在改進點:根據具體需求調整min_count引數的設定。

驗證與視覺化

透過上述步驟處理後的資料應該能夠確保每小時都有60個事件。最終視覺化結果應該更加連貫且準確。

interpolated.resample("h").size().plot()
interpolated.resample("D").sum().plot()

內容解密:

  • 程式碼解說:此段程式碼分別對每小時和每日重取樣並繪製事件大小和總和圖表。
  • 設計考量:這些圖表有助於驗證資料處理結果是否符合預期。
  • 技術原理:重取樣與視覺化是時間序列資料分析中的基本步驟。
  • 潛在改進點:可以增加更多細節級別(如十五分鐘級)來進一步驗證結果。