iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
自我挑戰組

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

[Day 17] 誰是全平台最有價值的超級買家?用 Pandas 打造 RFM 客戶基底寬表

  • 分享至 

  • xImage
  •  

告別千人一面,找出貢獻營收的關鍵少數

在 Day 16 中,我們解開了買家的金流偏好,證實分期付款是撬動 4 倍客單價的核心槓桿。

然而,當平台累積了近 10 萬筆訂單,營運主管最常問的下一個問題是:「我們平台到底有沒有忠誠的『超級大客』?誰買得最多、買得最貴?我們該把行銷預算砸在誰身上?」

在客戶關係管理(CRM)與用戶增長領域,最權威且歷久不衰的分析框架正是 RFM 模型:

  • R (Recency) 最近消費天數: 距離上次下單隔了多久?越近期消費的顧客,再次啟動的成本越低。

  • F (Frequency) 消費頻次: 終身在平台下過幾次單?消費次數代表顧客對平台的依賴度。

  • M (Monetary) 消費總金額: 累計貢獻了多少營收?消費總額直接決定了顧客的終身商業價值(LTV)。

今天我們將動手打造這張 RFM 客戶基底寬表,並避開 Olist 數據中最隱密的「身分識別陷阱」,
揪出全平台最具價值的超級買家!

步驟一:避開致命陷阱——customer_id vs. customer_unique_id

很多新手在做客戶分群時,會習慣性直接對訂單表或顧客表裡的 customer_id 執行 groupby。

這是在 Olist 資料集中最嚴重的致命失誤!

我們先來檢驗 olist_customers_dataset 的欄位設計:

import pandas as pd

# 1. 從資料庫字典取出顧客表
customers = olist_db['olist_customers_dataset'].copy()

# 2. 檢驗兩個客戶代碼的唯一值數量
print(f"customer_id 唯一值筆數: {customers['customer_id'].nunique():,}")
print(f"customer_unique_id 唯一值筆數: {customers['customer_unique_id'].nunique():,}")

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260924/20136155SYIWR7naTF.png

資料陷阱拆解:

  • customer_id: 只是單次結帳的「會話交易代碼(Session Token)」,每一次買家下單,

  • 系統就會隨機生成一個新的 customer_id。如果拿它當分組鍵,所有人的消費頻次(Frequency)永遠等於 1!

  • customer_unique_id: 才是真正代表「現實生活中的同一個自然人」的真實身分識別碼。

因此,在建構任何用戶模型時,唯一的合法分組鍵只有 customer_unique_id。

步驟二:串接真實顧客身分,計算單筆訂單總支出

我們將 Day 8 產出的有效訂單大表 valid_orders 與顧客表串聯,把顧客的真實身分找回來,
並計算每筆訂單的結帳總額(商品金額 + 運費):

# 1. 串接有效訂單與顧客真實身分
rfm_orders = pd.merge(
    valid_orders[['order_id', 'customer_id', 'order_purchase_timestamp', 'total_item_price', 'total_freight_value']],
    customers[['customer_id', 'customer_unique_id']],
    on='customer_id',
    how='inner'
)

# 2. 計算每筆訂單顧客的實際總支出(含運費)
rfm_orders['order_total_amount'] = (
    rfm_orders['total_item_price'] + rfm_orders['total_freight_value']
)

# 檢視合併樣本
rfm_orders[['order_id', 'customer_unique_id', 'order_purchase_timestamp', 'order_total_amount']].head(3)

實作 :
https://ithelp.ithome.com.tw/upload/images/20260924/20136155ej6I3XoeS6.png

步驟三:設定時間基準日 (Snapshot Date)

在計算 Recency(距離上次購買天數)時,標準公式為:

Recency = 時間基準日 - 該顧客最後一次下單時間

在即時生產環境中,基準日通常是 datetime.now()。
但在分析歷史資料集時,若直接拿今天的日期去減,所有顧客的 Recency 都會落在數千天以上,
徹底失去相對比較的意義。

專業作法:
以資料集中「最後一筆訂單發生的隔天」作為虛擬的分析基準日(Snapshot Date):

# 取資料集中最大購買日期的次日為基準日
snapshot_date = rfm_orders['order_purchase_timestamp'].max() + pd.Timedelta(days=1)
print(f"RFM 計算基準日 (Snapshot Date): {snapshot_date.strftime('%Y-%m-%d %H:%M:%S')}")

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260924/20136155UxdoZZuKlA.png

步驟四:Groupby 聚合——打造 RFM 客戶基底寬表

現在我們以 customer_unique_id 為核心,使用一氣呵成的聚合語法提煉每位顧客的 R、F、M 原始數值:

# 依顧客真實身分聚合計算 RFM 指標
rfm_table = rfm_orders.groupby('customer_unique_id').agg(
    # Recency: 基準日減去最近一次下單日(換算為天數)
    recency=('order_purchase_timestamp', lambda x: (snapshot_date - x.max()).days),
    # Frequency: 該用戶累計下過幾張有效訂單
    frequency=('order_id', 'nunique'),
    # Monetary: 該用戶累計貢獻的總營收
    monetary=('order_total_amount', 'sum')
).reset_index()

# 整理數值位數
rfm_table['monetary'] = rfm_table['monetary'].round(2)

# 檢視 RFM 表前五筆資料
rfm_table.head(5)

實作:

https://ithelp.ithome.com.tw/upload/images/20260924/20136155icKQ7n4u33.png

步驟五:資料輪廓體檢——誰是全平台最強超級買家?

建好寬表後,我們下 .describe() 檢驗數據分佈,並找出全平台累計消費最高與下單次數最多的「超級大戶」:

# 1. 檢視分佈統計
print(rfm_table[['recency', 'frequency', 'monetary']].describe().round(2))

# 2. 依消費金額 (Monetary) 降冪排序,檢視全平台 Top 5 超級大客
top_spenders = rfm_table.sort_values(by='monetary', ascending=False).head(5)
print("\n--- 全平台累計消費金額 Top 5 買家 ---")
print(top_spenders)

實作區 :

https://ithelp.ithome.com.tw/upload/images/20260924/201361555SY1DqDnBR.png

從數據看出的殘酷真相與驚人發現:

  • 消費頻次(Frequency)的殘酷真相:
    frequency 的 75% 甚至 95% 分位數全部都是 1!全平台近 10 萬名獨立買家中,
    超過 96% 的人終身「只買 過這一次」。這反映了電商平台獲取新客成本極高,
    但回購率卻極度疲軟的營運危機。
  • 誰是全平台最強大客?
    雖然回購次數普遍只有 1~2 次,但頂級超級大戶的消費力驚人:
    > - 榜首買家累計消費金額飆破 13,000 BRL(是全體平均客單價 165 BRL 的近 80 倍!)。
    > - 這些大客往往是集中採購高單價電子產品、專業設備或批發用途的個人商家。

今天我們完成了電商用戶價值建模最重要的一哩路:

  • 身分代碼校正: 識破 customer_id 陷阱,堅持以 customer_unique_id 確保頻次計算精準。

  • 確立基準錨點: 掌握歷史數據分析中設定 Snapshot Date 的標準 SOP。

  • 完成 RFM 寬表: 產出近 10 萬名買家的 R、F、M 原始特徵,並鎖定了頂級大客的名單。

我們發現 Frequency 有超過 96% 都是 1,如果直接使用傳統的五等分位數(pd.qcut)來打分數,
程式一定會報錯(因為分位點重複無法切分)。
明天 Day 18,我們將展示如何運用量身打造的自訂評分分箱(RFM Scoring),
並正式將顧客劃分為「核心 VIP」、「潛力新客」、「流失警戒群」等具備落地指導價值的客群名單!


上一篇
[Day 16] 沒分期就沒營收?拆解巴西電商支付偏好與高客單價的「分期槓桿」
下一篇
[Day 18] 從指標到決策地圖:打造 RFM 顧客價值金字塔與分群行銷策略
系列文
拯救混亂數據:30 天 Python 輕量級 ETL 與電商關聯資料分析 共 19 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言