第 15 章 資料分析:平均數、變異數與標準差¶
本章重點:
- 理解「平均數」的多種形式:算術平均數、中位數、眾數。
- 了解「變異數」與「標準差」如何量化資料的離散程度。
- 使用 Python / SymPy 計算平均數、變異數與標準差。
- 區分「母體」與「樣本」的變異數與標準差(分母是 $n$ 還是 $n-1$)。
- 用簡單圖形與模擬了解「資料集中」與「資料分散」的差異。
- 透過幾個啟發性例子,把統計量與現實情境(成績、薪資、量測誤差)做連結。
本章不會深談推論統計(信賴區間、假設檢定等), 而是聚焦在常見的「描述統計量」,讓你能用 Python 快速計算並初步解讀資料。
15.1 資料與數列:從一串數字開始¶
我們把收集到的觀察值稱為「資料」,例如:
- 一個班級的數學成績:
[72, 88, 90, 65, 90, 78, 85]。 - 每天量測的氣溫、股價、心跳次數⋯⋯
統計的第一步,就是先把資料整理成一串數字,然後問:
- 這些數字「大致上」多大?(中心位置)
- 這些數字「大致上」差異多大?(分散程度)
在 Python 中,我們可以用 list 來存一串資料:
scores = [72, 88, 90, 65, 90, 78, 85]
scores
[72, 88, 90, 65, 90, 78, 85]
15.2 算術平均數(mean)¶
最常見的「平均」是算術平均數:
$$\bar{x} = \frac{1}{n} \sum_{i=1}^n x_i,$$
其中 $x_1, x_2, \dots, x_n$ 是資料,$n$ 是資料筆數。
在 Python 中可以用 sum 與 len。
先用純 Python:
scores = [72, 88, 90, 65, 90, 78, 85]
mean_py = sum(scores)/len(scores)
mean_py
81.14285714285714
再用 SymPy 計算一次,順便感受符號運算的寫法:
import sympy as sp
sp.init_printing()
data = sp.Array(scores)
mean_sym = sp.nsimplify(sum(data)/len(data))
mean_sym
可以利用專門做數值運算的 numpy 套件裡的函數來計算平均數:
import numpy as np
np.mean(scores)
15.3 中位數(median)與眾數(mode)¶
除了算術平均數之外,常見的中心位置指標還有:
- 中位數:將資料由小到大排序後,「正中間」的那個值。
- 若資料筆數為奇數,直接取中間那個。
- 若為偶數,取中間兩數的平均。
- 眾數:資料中出現頻率最高的數值(可能不唯一)。
這三種指標在面對「極端值」時的穩定程度不同, 例如薪資、房價常用中位數來描述較具代表性的水平。
scores_sorted = sorted(scores)
scores_sorted
計算中位數與眾數,numpy 和 statistics 套件裡有現成的統計函數:
import numpy as np
import statistics
median_val = np.median(scores)
mode_val = statistics.multimode(scores)
median_val, mode_val
15.4 變異數與標準差:資料「散不散」¶
兩組平均一樣的資料,可能有完全不同的分散程度:
- 組 A:
[70, 70, 70, 70](大家分數都差不多) - 組 B:
[40, 60, 80, 100](差異很大)
為了量化「分散程度」,我們定義:
- 偏差(deviation):每個資料減去平均數 $x_i - \bar{x}$。
- 平方偏差:$(x_i - \bar{x})^2$。
- 變異數(variance):平方偏差的平均。
有兩種常見版本:
- 母體變異數:$\displaystyle \sigma^2 = \frac{1}{N}\sum_{i=1}^N (x_i - \mu)^2$。
- 樣本變異數:$\displaystyle s^2 = \frac{1}{n-1}\sum_{i=1}^n (x_i - \bar{x})^2$。
母體/樣本的差別涉及統計推論,本章先重點記住:
樣本變異數多用 $n-1$ 做分母,反映「資料有限」時的一種校正。
標準差(standard deviation) 則是變異數開根號:
$$\sigma = \sqrt{\sigma^2}, \quad s = \sqrt{s^2}.$$
好處是單位與原始資料相同,較容易解讀(例如:分數的標準差仍然是「分」)。
15.5 用 Python / SymPy 手工計算變異數與標準差¶
我們用剛才的成績資料,依照定義一步步算出樣本變異數與樣本標準差。
scores = [72, 88, 90, 65, 90, 78, 85]
n = len(scores)
mean_val = sum(scores)/n
deviations = [x - mean_val for x in scores]
squared_dev = [(x - mean_val)**2 for x in scores]
sample_variance = sum(squared_dev)/(n-1)
sample_std = sample_variance**0.5
mean_val, deviations, squared_dev, sample_variance, sample_std
你可以觀察:
- 有些偏差為正(高於平均)、有些為負(低於平均)。
- 若直接把偏差加總,多半接近 0(正負相抵)。
- 因此我們先平方,再取平均,才得到「分散程度」。
可以用 numpy 中函數來計算變異數和標準差:
population_var1 = np.var(scores, ddof=0) # 母體變異數
sample_var1 = np.var(scores, ddof=1) # 樣本變異數
population_std1 = np.std(scores, ddof=0) # 母體標準差
sample_std1 = np.std(scores, ddof=1) # 樣本標準差
population_var1, sample_var1, population_std1, sample_std1
SymPy 也可以幫忙計算,這裡示範用符號方式定義平均與樣本變異數:
data_syms = sp.Array(scores)
n = len(data_syms)
mean_sym = sum(data_syms)/n
sample_var_sym = sum((x - mean_sym)**2 for x in data_syms)/(n-1)
sample_std_sym = sp.sqrt(sample_var_sym)
sp.simplify(mean_sym), sp.simplify(sample_var_sym), sp.nsimplify(sample_std_sym)
用小數表示:
sp.simplify(mean_sym).n(), sp.simplify(sample_var_sym).n(), sp.nsimplify(sample_std_sym).n()
15.6 啟發性例子一:平均一樣,標準差不同¶
考慮兩組成績:
- A 組:
[70, 70, 70, 70] - B 組:
[40, 60, 80, 100]
兩組的平均數都是 70,但明顯 B 組差異較大。
我們用 Python 比較兩組的標準差:
A = [70, 70, 70, 70]
B = [40, 60, 80, 100]
def sample_std(data):
n = len(data)
mean_val = sum(data)/n
return (sum((x - mean_val)**2 for x in data)/(n-1))**0.5
mean_A, std_A = sum(A)/len(A), sample_std(A)
mean_B, std_B = sum(B)/len(B), sample_std(B)
mean_A, std_A, mean_B, std_B
結果顯示兩組平均相同,但 B 組標準差遠大於 A 組。
解讀:
- A 組:每個人都差不多 70 分。
- B 組:有人很低分,有人很高分。
標準差是描述「不均勻程度」的好工具。
15.7 啟發性例子二:極端值對平均與中位數的影響¶
考慮某新創公司五位員工的月薪(單位:萬元):
- 原本:
[35, 36, 37, 38, 40]。 - 公司後來找來一位高薪顧問:月薪 200 萬。
新的薪資資料:[35, 36, 37, 38, 40, 200]。
比較平均與中位數的變化:
salaries = [35, 36, 37, 38, 40]
salaries_extreme = [35, 36, 37, 38, 40, 200]
def mean(data):
return sum(data)/len(data)
from statistics import median
mean1, median1 = mean(salaries), median(salaries)
mean2, median2 = mean(salaries_extreme), median(salaries_extreme)
mean1, median1, mean2, median2
可以看到:
- 加入極端值後,平均數被拉得很高。
- 中位數變化不大,仍然接近多數人薪資的典型水準。
因此在有極端值的情境(如薪資、房價),中位數常較能代表「典型」的情況。
15.8 啟發性例子三:量測誤差與標準差¶
假設你用同一支溫度計量測室溫 10 次,得到(單位:°C):
[25.1, 24.9, 25.0, 25.2, 25.0, 24.8, 25.1, 25.0, 24.9, 25.1]
我們想知道:
- 平均溫度大約多少?
- 測量值大致上會在平均值左右多少範圍內擺盪?(標準差)
temps = [25.1, 24.9, 25.0, 25.2, 25.0, 24.8, 25.1, 25.0, 24.9, 25.1]
mean_temp = sum(temps)/len(temps)
std_temp = sample_std(temps)
mean_temp, std_temp
我們可以粗略說:室溫約為 平均 ± 1 標準差,例如約 $25.0 ± 0.12$ °C,
代表大部分量測值落在這個範圍內。
在實驗科學中,標準差常用來描述測量的不確定性。
15.9 用 Python 簡單畫圖看資料分布(概念示意)¶
在資料分析中,除了計算數字指標外,「畫圖」非常重要。
在 Jupyter Notebook 裡,你可以使用 matplotlib 畫直方圖(histogram)或散佈圖。
這裡做一個簡單範例,展示溫度資料的直方圖:
import matplotlib.pyplot as plt
temps = [25.1, 24.9, 25.0, 25.2, 25.0, 24.8, 25.1, 25.0, 24.9, 25.1]
plt.hist(temps, bins=5)
plt.xlabel('Temperature (°C)')
plt.ylabel('Frequency')
plt.title('Temperature Measurements Histogram')
plt.show()
你可以嘗試:
- 增加資料筆數(模擬更多測量)。
- 改變
bins的數量,看看直方圖形狀怎麼改變。
圖形與數值統計量搭配,會讓你對資料的理解更完整。
15.10 樣本 vs 母體:符號觀點¶
多數現實情況下,我們只拿到母體的一小部分資料(樣本), 卻想了解整個母體的真正平均與變異數。
因此:
- $\bar{x}$(樣本平均)用來估計母體平均 $\mu$。
- $s^2$(樣本變異數,分母 $n-1$)用來估計母體變異數 $\sigma^2$。
這些估計量的性質(是否偏差、變異大小)屬於「推論統計」範疇, 在本章只作觀念上的提醒:
在用統計軟體時,要留意「變異數」與「標準差」究竟是用 $n$ 還是 $n-1$。
15.11 本章小結¶
本章你學到了:
- 如何用 Python / SymPy 計算算術平均數、中位數與眾數。
- 變異數與標準差的定義,並用程式實作樣本變異數與樣本標準差。
- 「平均相同但標準差不同」的資料,在解讀上有很大差異。
- 極端值對平均與中位數的影響,以及為何在某些情境下中位數更具代表性。
- 標準差在量測誤差描述中的意義,以及用簡單直方圖看資料分布。
- 樣本與母體的區分,及其在變異數定義上的差別($n$ vs $n-1$)。
這些都是日後學習統計、機器學習與資料科學的重要基礎。
15.12 練習題¶
請在本 Notebook 中新增儲存格,試著完成以下練習:
基本平均與中位數
(a) 對資料[10, 12, 13, 15, 20]計算算術平均數與中位數。
(b) 再加入一個極端值 100,變成[10, 12, 13, 15, 20, 100],重新計算。
(c) 比較兩種情況下平均數與中位數的變化,寫下你的觀察。樣本標準差計算
(a) 寫一個函數sample_variance(data),回傳樣本變異數(分母 $n-1$)。
(b) 寫一個函數sample_std(data),回傳樣本標準差。
(c) 用這兩個函數計算第 15.6 節 A 組與 B 組成績的變異數與標準差。兩組資料的比較
有兩家公司的年終獎金資料(單位:萬元):- 甲公司:
[1, 1, 1, 1, 1, 1, 1, 1] - 乙公司:
[0, 0, 0, 0, 0, 4, 4, 4]
(a) 計算兩家公司的平均數、中位數與標準差。
(b) 從「公平性」與「風險」角度,討論你更想在哪一家公司領年終(沒有標準答案)。
- 甲公司:
量測資料與直方圖
(a) 用random.normalvariate(μ, σ)產生 100 筆近似常態的模擬溫度資料(例如 μ=25, σ=0.2)。
(b) 計算這 100 筆資料的平均數與標準差。
(c) 畫出直方圖,觀察資料大致集中在哪個範圍。
(d) 試著增加到 1000 筆資料,觀察直方圖是否更接近「鐘形曲線」。母體 vs 樣本的差異(實驗觀察)
(a) 先建立一個「母體」:例如用 Python 產生 10000 個均勻分布在 [0,1] 的數字。
(b) 從這個母體中隨機抽 50 個樣本,計算樣本平均與樣本標準差。
(c) 重複抽樣 50 次,記錄每一次的樣本平均與樣本標準差。
(d) 用簡單圖或摘要數字,觀察樣本統計量如何圍繞著「母體」的真實平均與變異數。加分題:Z 分數(標準化)
對於資料中的每一個 $x$,定義 Z 分數:
$$z = \frac{x - \bar{x}}{s}.$$
(a) 寫一個函數z_scores(data),回傳每筆資料的 Z 分數。
(b) 對第 15.8 節的溫度資料計算 Z 分數,觀察哪些測量值偏離平均較多。
(c) 思考:若某測量值的 |z| 很大(例如大於 3),你會懷疑什麼?