iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
自我挑戰組

數據新手村:統計系畢業生 30 天打怪升級之旅系列 第 28

Day 28 - 專案實戰(一):Olist 整體銷售趨勢視覺化分析

  • 分享至 

  • xImage
  •  

大家好,歡迎來到數據新手村的第二十八天!在鐵人賽的最後幾天,將進入「專案實戰」階段。

今天,不再學習單一的函式或語法,而是要將過去幾週學到的所有技能——Pandas 的資料處理、時間序列分析、Group By 聚合以及 Matplotlib/Seaborn 的視覺化——全部整合起來,完成我們的第一個端到端 (End-to-End) 的迷你專案。

任務定義:分析平台整體銷售趨勢

身為 Olist 平台的數據分析師,老闆給我們第一個任務:

「請分析我們平台從 2017 年到 2018 年的『整體月銷售額』趨勢,畫出圖表,並告訴我你的觀察與發現。」

為了回答這個問題,作戰計畫分為以下四步:

  1. 資料準備: 讀取並合併 orderspayments 兩張表,並處理好時間欄位。
  2. 時間序列聚合: 將逐筆的訂單資料,彙總成「每月」的總銷售額。
  3. 趨勢視覺化: 將聚合後的結果,用折線圖清晰地呈現出來。
  4. 結論與洞見: 解讀圖表,向老闆報告我們的發現。

步驟一:資料準備

第一步是準備好我們需要的乾淨資料。我們需要 orders 表中的下單時間 (order_purchase_timestamp) 和 payments 表中的支付金額 (payment_value)。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# --- 設定中文字體 ---
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei'] 
plt.rcParams['axes.unicode_minus'] = False 

# --- 讀取與合併 ---
orders_df = pd.read_csv('../../data/olist_datasets/olist_orders_dataset.csv')
payments_df = pd.read_csv('../../data/olist_datasets/olist_order_payments_dataset.csv')
df = pd.merge(orders_df, payments_df, on='order_id', how='left')

# --- 清理與轉換 ---
# 1. 處理缺失值
df = df.dropna(subset=['order_purchase_timestamp', 'payment_value'])

# 2. 轉換時間欄位 (Day 20 的核心技巧)
df['order_purchase_timestamp'] = pd.to_datetime(df['order_purchase_timestamp'])

# 3. (新技巧!) 將時間設定為索引 (Index)
# 這麼做可以解鎖 Pandas 強大的時間序列分析能力
df.set_index('order_purchase_timestamp', inplace=True)

print("資料準備完成,並將時間設定為索引:")
df[['payment_value']].info()

輸出結果:

資料準備完成,並將時間設定為索引:
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 103886 entries, 2017-10-02 10:56:33 to 2018-03-08 20:57:30
Data columns (total 1 columns):
 #   Column         Non-Null Count   Dtype  
---  ------         --------------   -----  
 0   payment_value  103886 non-null  float64
dtypes: float64(1)
memory usage: 1.6 MB

步驟二:時間序列聚合 (.resample())

我們現在擁有的是每一筆訂單的詳細時間。為了分析「月銷售額」,我們需要將這些數據按「月」來分組聚合。這時,Pandas 針對時間序列提供的專用 groupby——.resample() 方法就登場了!

.resample() 可以讓我們非常輕易地改變時間序列的「頻率」(例如,從每日數據變為每月數據)。


# 使用 .resample() 將數據按「月 (ME)」進行重採樣
# 'M' 代表 Month End frequency (月底頻率)
# 接著用 .sum() 告訴 resample 我們要計算每個月的「總和」
monthly_sales = df['payment_value'].resample('ME').sum()

print("按月聚合後的銷售數據 (前五筆):")
print(monthly_sales.head())

輸出結果:
按月聚合後的銷售數據 (前五筆):
order_purchase_timestamp
2016-09-30 252.24
2016-10-31 59090.48
2016-11-30 0.00
2016-12-31 19.62
2017-01-31 138488.04
Freq: ME, Name: payment_value, dtype: float64

步驟三:趨勢視覺化

數據聚合完成後,我們就可以用 Day 25 學到的技巧,將這個 monthly_sales Series 畫成折線圖。

plt.figure(figsize=(15, 7))

# Pandas DataFrame/Series 可以直接呼叫 .plot() 方法來繪圖
monthly_sales.plot(kind='line', marker='o', linestyle='-')

plt.title('Olist 平台月銷售額趨勢 (2016-2018)', fontsize=16)
plt.xlabel('日期', fontsize=12)
plt.ylabel('總銷售額', fontsize=12)
plt.grid(True) # 加上格線
plt.show()

輸出結果:
https://ithelp.ithome.com.tw/upload/images/20251011/20178546NceVoOCFnK.png

步驟四:結論與洞見

有了這張圖表,我們就可以自信地向老闆報告了:

從上圖中,我們可以清楚地觀察到幾個關鍵趨勢:

快速成長期 (2017): 整體來看,平台銷售額從 2017 年初到 2017 年底,呈現顯著的階梯式爆發成長,證明平台在該年度的商業策略非常成功。

季節性模式 (Seasonal Pattern): 我們可以看到一個清晰的季節性規律,每年年底(約 11 月)都是一個銷售高峰,這很可能與黑色星期五或聖誕節的購物季有關。

趨勢穩定與異常點 (2018): 進入 2018 年後,銷售額趨於穩定,但在年中之後似乎出現了數據下滑。(註:經過查證,Olist 公開數據集主要涵蓋到 2018 年 9 月,因此 9 月之後的數據不完整是正常現象,並非真實的業績衰退。)


結語

今天,我們完成了第一個端到端的分析專案!從提出問題、準備數據、使用 .resample() 進行時間序列聚合,到最終的視覺化與洞察解讀,您已經完整地體驗了一次數據分析師的日常工作流程。

我們今天將分析結果呈現在圖表上,但這些寶貴的、經過清理與聚合的數據,應該如何被儲存起來以便未來重複使用呢?明天,Day 29,我們將回到數據的歸宿——將 Pandas 的分析成果存入 MySQL 資料庫,並學習用 SQL 進行驗證查詢,完成我們數據工作流的最後一塊拼圖!


上一篇
Day 27 - Matplotlib 散點圖與 Seaborn 初探
下一篇
Day 29 - 將 Pandas 成果存入 MySQL 並用 SQL 查詢
系列文
數據新手村:統計系畢業生 30 天打怪升級之旅30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言