iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
自我挑戰組

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

[Day 08] 從宏觀走向洞察:剔除無效訂單,精算真實電商月營收 (GMV)

  • 分享至 

  • xImage
  •  

宏觀分析的第一步:釐清有效訂單的認列標準

昨天我們成功打通了訂單主表、客戶表與明細表,整合出一張具備完整維度的寬表 final_orders。

當手上有一張包含營收的寬表時,許多人的第一反應是直接下 df['total_item_price'].sum() 來計算公司賺了多少錢。然而,在真實的商業世界裡,這種算法產出的往往是「灌水的假營收」。

在經營電商時,未付款、中途取消、缺貨未履約的訂單,都不能認列為公司實際入帳的成交總額(Gross Merchandise Volume, GMV)。今天我們將從宏觀視角切入,先擠出數據中的「水分」,再精準計算出 Olist 每個月的真實營收走勢。

步驟一:檢驗訂單履約狀態,定義「有效訂單」

我們先來盤點 order_status 欄位中到底藏了哪些狀態:

# 1. 檢視訂單狀態分布佔比
status_counts = final_orders['order_status'].value_counts()
status_ratio = final_orders['order_status'].value_counts(normalize=True) * 100

pd.DataFrame({'訂單數': status_counts, '佔比(%)': status_ratio.round(2)})

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260915/201361555VZVFjUKmu.png

從統計可以看出,有的訂單處於非最終交付狀態。如果我們不加以過濾:

  • canceled(取消單)會虛增營業額。

  • unavailable(缺貨未履約)會干擾真實市場需求的營收換算。

為了確保財務與營運分析的嚴謹度,我們定義只有 order_status == 'delivered' 的交易才屬於有效認列營收:

# 篩選已送達顧客的有效成交訂單
valid_orders = final_orders[final_orders['order_status'] == 'delivered'].copy()

print(f"原始訂單總數: {len(final_orders):,} 筆")
print(f"有效成交訂單數: {len(valid_orders):,} 筆")
print(f"已剔除無效/未完成訂單: {len(final_orders) - len(valid_orders):,} 筆")

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260915/20136155I863NMbyLe.png

步驟二:時序特徵工程——提煉「年-月」維度

在 Day 5 的資料清洗中,我們已經將 order_purchase_timestamp 轉換為標準的 datetime64 格式。

現在,我們不需要複雜的字串切割,直接利用 Pandas 的 .dt 存取器搭配 to_period('M'),即可快速將精確到秒的時間戳記聚合為便於趨勢比較的「月份區間」:

# 新增 'order_year_month' 欄位(格式為 YYYY-MM)
valid_orders['order_year_month'] = valid_orders['order_purchase_timestamp'].dt.to_period('M')

# 檢視處理後的對照樣本
valid_orders[['order_purchase_timestamp', 'order_year_month']].head(3)

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260915/20136155pnB9aUobTR.png

步驟三:實作 Groupby 聚合,精算月度 GMV 與單量

維度切分完成後,我們同時計算電商最關注的兩個關鍵指標:

  • GMV (Gross Merchandise Volume): 當月商品總成交金額。

  • Order Volume: 當月成功履約的訂單總數。

# 依月份聚合計算總 GMV 與總訂單數
monthly_metrics = valid_orders.groupby('order_year_month').agg(
    total_gmv=('total_item_price', 'sum'),
    order_count=('order_id', 'count')
).reset_index()

# 計算各月平均客單價 (AOV: Average Order Value)
monthly_metrics['aov'] = (monthly_metrics['total_gmv'] / monthly_metrics['order_count']).round(2)

# 轉換 Period 為字串以利輸出與後續作圖
monthly_metrics['order_year_month'] = monthly_metrics['order_year_month'].astype(str)

monthly_metrics.head(10)

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260915/20136155k8CT2UAV0Y.png

步驟四:洞察 —— 識破 2018 年 9 月的數據斷崖

當數據拉到最後幾個月(monthly_metrics.tail())時,會發現一個關鍵的數據異常:

2018 年 1 月至 8 月,月 GMV 穩定維持在約 85 萬至 97 萬雷亞爾(BRL)的高檔。

但到了 2018 年 9 月,GMV 卻瞬間雪崩只剩微量紀錄。

# 觀察最後幾個月的月營收表現
monthly_metrics.tail(8)

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260915/20136155gUgfN4VTA9.png

這並不是平台營運發生崩盤,而是典型的資料庫取樣截止效應(Data Truncation):
該公開資料集的採集截止日為 2018 年 9 月初,因此 9 月份只有極少數尚未完成結算的資料。

實作結論:
在進行長期趨勢評估或預測模型訓練時,必須主動將 2018 年 9 月(含)以後的不完整月份剔除,
否則會得出「公司即將倒閉」的荒謬結論。
這正是數據健康檢查與業務常識結合的價值所在。

今天我們完成了從寬表到商業指標的轉化:

  • 1.拒絕營收灌水: 透過 order_status 嚴格把關,剔除未履約訂單。

  • 2.時序特徵提煉: 善用 .dt.to_period('M') 完成標準月份區間建立。

  • 3.發現數據截斷: 透過數據尾端檢驗,識別出資料收集邊界帶來的斷崖假象。

我們已經在宏觀維度確認了平台的成長曲線。既然整體 GMV 呈現向上擴張的格局,那麼究竟是哪些「行政區」在貢獻主力消費?明天,我們將下鑽至地理維度,分析巴西各州的客單價 (AOV) 與訂單集中度!


上一篇
[Day 07] 拆解一對多 Merge 陷阱與 Groupby 營收聚合實戰
下一篇
[Day 09] 走出平均值盲點:巴西各州單量集中度與客單價 (AOV) 反差
系列文
拯救混亂數據:30 天 Python 輕量級 ETL 與電商關聯資料分析15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言