iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
自我挑戰組

拯救混亂數據:30 天 Python 輕量級 ETL 與電商關聯資料分析系列 第 5

[Day 05] 資料清洗 Transform:批次校正時間格式與空值邏輯判定

  • 分享至 

  • xImage
  •  

進入 ETL 的核心「Transform」

昨天我們取出最重要的「訂單主表 (orders)」做了一次徹底的健康檢查。
我們成功抓出了今天必須動手修理的兩個問題:

假的時間: 系統把時間當成了普通文字。
合理的留白 (空值): 「送達時間」有 2965 個空缺。
今天,我們正式進入 ETL 流程中的 Transform(資料轉換與清洗) 階段。
我們要把假的時間變回真時間,並用實際的數據來證實昨天提到的邏輯!

步驟一:讓假時間現出原形 (String to Datetime)

在訂單主表中,總共有 5 個與時間相關的欄位(例如:下單時間、付款時間、發貨時間等)。
也許按照初學者的直覺,可能會連寫 5 行 pd.to_datetime() 來轉換格式,但這又違背了我們在 Day 3 提到的 DRY (Don't Repeat Yourself) 原則
身為講究效率的實戰派,我把這些欄位名稱裝進一個 List,用一個簡單的 for 迴圈就能優雅解決:

# 1. 找出所有需要轉換的時間欄位名稱
time_columns = [
    'order_purchase_timestamp',      # 購買時間
    'order_approved_at',             # 付款確認時間
    'order_delivered_carrier_date',  # 物流發貨時間
    'order_delivered_customer_date', # 送達顧客時間
    'order_estimated_delivery_date'  # 預計送達時間
]

# 2. 用一個迴圈,把文字字串批次轉換為真正的 datetime 格式
for col in time_columns:
    orders[col] = pd.to_datetime(orders[col])

# 3. 再次檢查,確認轉換成功
orders.info()

實作圖 :

https://ithelp.ithome.com.tw/upload/images/20260912/20136155fYDwr9q6hN.png

太好了!現在它們是真正的「時間」了。
未來我們就能輕鬆拿「送達時間」減去「下單時間」,精準算出一件包裹到底在路上漂流了幾天。

步驟二:用數據證實「合理的留白」(處理 NaN)

時間格式搞定後,我們要來面對那將近 2965 個沒有「送達顧客時間 (order_delivered_customer_date)」的空值。

昨天我們用網購的常理推斷:「如果訂單被取消,包裹沒出貨,自然就不會有送達時間。」
現在,我們用 Pandas 來驗證這個假設。
我們把那 2965 筆缺少送達時間的訂單抓出來,看看它們的「訂單狀態 (order_status)」到底是什麼?

# 1. 篩選出「沒有送達時間」的訂單
missing_delivery = orders[orders['order_delivered_customer_date'].isnull()]

# 2. 統計這些空值訂單的「訂單狀態」數量
print(missing_delivery['order_status'].value_counts())

實作圖 :

https://ithelp.ithome.com.tw/upload/images/20260912/20136155zQ2pBrQOAZ.png

真相大白! 從結果可以看出,這些沒有送達時間的訂單,絕大多數的狀態是:

  • hipped(還在物流車上,沒送到)
  • anceled(顧客中途取消了)
  • navailable(商品缺貨無法出貨)

這證明了我們的判斷完全正確:這些空值不是系統出錯,而是現實世界中本來就會發生的正常狀況!

步驟三:決策時刻,這 2965 筆資料空值該刪嗎?

我的結論是:絕對不要用 dropna() 把這整行資料刪掉!

如果你為了畫面乾淨把它們刪了,老闆明天問你:「這個月有多少訂單被取消?退貨率是多少?」
你的數據就會少算這 2965 筆資料,導致嚴重的分析問題。

在 Pandas 的世界裡,針對時間欄位的空值,最好的處理方式就是「保留原樣」。
轉換格式後,Pandas 會自動把它們顯示為 NaT (Not a Time)。

  • 我們要計算「物流平均天數」時,把這些 NaT 排除就好。

  • 我們要分析「訂單取消率」時,這 2965 筆又是不可或缺的重要數據。


今天我們完成了兩件非常重要的 Transform 任務:

釐清空值邏輯:我們沒有盲目刪除空值,而是透過數據佐證,成功保留了代表「訂單取消」或「運送中」的紀錄。

現在,最重要的「訂單主表」已經被我們洗得乾乾淨淨了。
但光有骨架還不夠,明天我們將拿出另一張表,並實作資料庫分析中最經典的 JOIN(合併) 技巧,把訂單與客戶資料串聯起來!


上一篇
[Day 04] 數據健康檢查:不急著畫圖,先用 EDA 摸清「訂單主表」的底細
下一篇
[Day 06] ETL 核心技法:用 pd.merge 實作左外部合併與資料粒度驗證
系列文
拯救混亂數據:30 天 Python 輕量級 ETL 與電商關聯資料分析6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言