第 15 章 資料分析:平均數、變異數與標準差¶

本章重點:

  • 理解「平均數」的多種形式:算術平均數、中位數、眾數。
  • 了解「變異數」與「標準差」如何量化資料的離散程度。
  • 使用 Python / SymPy 計算平均數、變異數與標準差。
  • 區分「母體」與「樣本」的變異數與標準差(分母是 $n$ 還是 $n-1$)。
  • 用簡單圖形與模擬了解「資料集中」與「資料分散」的差異。
  • 透過幾個啟發性例子,把統計量與現實情境(成績、薪資、量測誤差)做連結。

本章不會深談推論統計(信賴區間、假設檢定等), 而是聚焦在常見的「描述統計量」,讓你能用 Python 快速計算並初步解讀資料。

15.1 資料與數列:從一串數字開始¶

我們把收集到的觀察值稱為「資料」,例如:

  • 一個班級的數學成績:[72, 88, 90, 65, 90, 78, 85]。
  • 每天量測的氣溫、股價、心跳次數⋯⋯

統計的第一步,就是先把資料整理成一串數字,然後問:

  • 這些數字「大致上」多大?(中心位置)
  • 這些數字「大致上」差異多大?(分散程度)

在 Python 中,我們可以用 list 來存一串資料:

In [1]:
scores = [72, 88, 90, 65, 90, 78, 85]
scores
Out[1]:
[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:

In [2]:
scores = [72, 88, 90, 65, 90, 78, 85]
mean_py = sum(scores)/len(scores)
mean_py
Out[2]:
81.14285714285714

再用 SymPy 計算一次,順便感受符號運算的寫法:

In [3]:
import sympy as sp
sp.init_printing()

data = sp.Array(scores)
mean_sym = sp.nsimplify(sum(data)/len(data))
mean_sym
Out[3]:
$\displaystyle \frac{568}{7}$

可以利用專門做數值運算的 numpy 套件裡的函數來計算平均數:

In [4]:
import numpy as np
np.mean(scores)
Out[4]:
$\displaystyle 81.1428571428571$

15.3 中位數(median)與眾數(mode)¶

除了算術平均數之外,常見的中心位置指標還有:

  • 中位數:將資料由小到大排序後,「正中間」的那個值。
    • 若資料筆數為奇數,直接取中間那個。
    • 若為偶數,取中間兩數的平均。
  • 眾數:資料中出現頻率最高的數值(可能不唯一)。

這三種指標在面對「極端值」時的穩定程度不同, 例如薪資、房價常用中位數來描述較具代表性的水平。

In [5]:
scores_sorted = sorted(scores)
scores_sorted
Out[5]:
$\displaystyle \left[ 65, \ 72, \ 78, \ 85, \ 88, \ 90, \ 90\right]$

計算中位數與眾數,numpy 和 statistics 套件裡有現成的統計函數:

In [6]:
import numpy as np
import statistics

median_val = np.median(scores)
mode_val = statistics.multimode(scores)

median_val, mode_val
Out[6]:
$\displaystyle \left( 85.0, \ \left[ 90\right]\right)$

15.4 變異數與標準差:資料「散不散」¶

兩組平均一樣的資料,可能有完全不同的分散程度:

  • 組 A:[70, 70, 70, 70](大家分數都差不多)
  • 組 B:[40, 60, 80, 100](差異很大)

為了量化「分散程度」,我們定義:

  1. 偏差(deviation):每個資料減去平均數 $x_i - \bar{x}$。
  2. 平方偏差:$(x_i - \bar{x})^2$。
  3. 變異數(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 手工計算變異數與標準差¶

我們用剛才的成績資料,依照定義一步步算出樣本變異數與樣本標準差。

In [7]:
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
Out[7]:
$\displaystyle \left( 81.1428571428571, \ \left[ -9.14285714285714, \ 6.85714285714286, \ 8.85714285714286, \ -16.1428571428571, \ 8.85714285714286, \ -3.14285714285714, \ 3.85714285714286\right], \ \left[ 83.5918367346938, \ 47.0204081632654, \ 78.4489795918368, \ 260.591836734694, \ 78.4489795918368, \ 9.87755102040814, \ 14.8775510204082\right], \ 95.4761904761905, \ 9.77119186569328\right)$

你可以觀察:

  • 有些偏差為正(高於平均)、有些為負(低於平均)。
  • 若直接把偏差加總,多半接近 0(正負相抵)。
  • 因此我們先平方,再取平均,才得到「分散程度」。

可以用 numpy 中函數來計算變異數和標準差:

In [8]:
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
Out[8]:
$\displaystyle \left( 81.8367346938776, \ 95.4761904761905, \ 9.04636582799289, \ 9.77119186569328\right)$

SymPy 也可以幫忙計算,這裡示範用符號方式定義平均與樣本變異數:

In [9]:
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)
Out[9]:
$\displaystyle \left( \frac{568}{7}, \ \frac{2005}{21}, \ \frac{\sqrt{42105}}{21}\right)$

用小數表示:

In [10]:
sp.simplify(mean_sym).n(), sp.simplify(sample_var_sym).n(), sp.nsimplify(sample_std_sym).n()
Out[10]:
$\displaystyle \left( 81.1428571428571, \ 95.4761904761905, \ 9.77119186569328\right)$

15.6 啟發性例子一:平均一樣,標準差不同¶

考慮兩組成績:

  • A 組:[70, 70, 70, 70]
  • B 組:[40, 60, 80, 100]

兩組的平均數都是 70,但明顯 B 組差異較大。

我們用 Python 比較兩組的標準差:

In [11]:
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
Out[11]:
$\displaystyle \left( 70.0, \ 0.0, \ 70.0, \ 25.8198889747161\right)$

結果顯示兩組平均相同,但 B 組標準差遠大於 A 組。

解讀:

  • A 組:每個人都差不多 70 分。
  • B 組:有人很低分,有人很高分。

標準差是描述「不均勻程度」的好工具。

15.7 啟發性例子二:極端值對平均與中位數的影響¶

考慮某新創公司五位員工的月薪(單位:萬元):

  • 原本:[35, 36, 37, 38, 40]。
  • 公司後來找來一位高薪顧問:月薪 200 萬。

新的薪資資料:[35, 36, 37, 38, 40, 200]。

比較平均與中位數的變化:

In [12]:
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
Out[12]:
$\displaystyle \left( 37.2, \ 37, \ 64.3333333333333, \ 37.5\right)$

可以看到:

  • 加入極端值後,平均數被拉得很高。
  • 中位數變化不大,仍然接近多數人薪資的典型水準。

因此在有極端值的情境(如薪資、房價),中位數常較能代表「典型」的情況。

15.8 啟發性例子三:量測誤差與標準差¶

假設你用同一支溫度計量測室溫 10 次,得到(單位:°C):

[25.1, 24.9, 25.0, 25.2, 25.0, 24.8, 25.1, 25.0, 24.9, 25.1]

我們想知道:

  • 平均溫度大約多少?
  • 測量值大致上會在平均值左右多少範圍內擺盪?(標準差)
In [13]:
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
Out[13]:
$\displaystyle \left( 25.01, \ 0.119721899973787\right)$

我們可以粗略說:室溫約為 平均 ± 1 標準差,例如約 $25.0 ± 0.12$ °C, 代表大部分量測值落在這個範圍內。

在實驗科學中,標準差常用來描述測量的不確定性。

15.9 用 Python 簡單畫圖看資料分布(概念示意)¶

在資料分析中,除了計算數字指標外,「畫圖」非常重要。

在 Jupyter Notebook 裡,你可以使用 matplotlib 畫直方圖(histogram)或散佈圖。 這裡做一個簡單範例,展示溫度資料的直方圖:

In [14]:
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()
No description has been provided for this image

你可以嘗試:

  • 增加資料筆數(模擬更多測量)。
  • 改變 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 中新增儲存格,試著完成以下練習:

  1. 基本平均與中位數
    (a) 對資料 [10, 12, 13, 15, 20] 計算算術平均數與中位數。
    (b) 再加入一個極端值 100,變成 [10, 12, 13, 15, 20, 100],重新計算。
    (c) 比較兩種情況下平均數與中位數的變化,寫下你的觀察。

  2. 樣本標準差計算
    (a) 寫一個函數 sample_variance(data),回傳樣本變異數(分母 $n-1$)。
    (b) 寫一個函數 sample_std(data),回傳樣本標準差。
    (c) 用這兩個函數計算第 15.6 節 A 組與 B 組成績的變異數與標準差。

  3. 兩組資料的比較
    有兩家公司的年終獎金資料(單位:萬元):

    • 甲公司:[1, 1, 1, 1, 1, 1, 1, 1]
    • 乙公司:[0, 0, 0, 0, 0, 4, 4, 4]
      (a) 計算兩家公司的平均數、中位數與標準差。
      (b) 從「公平性」與「風險」角度,討論你更想在哪一家公司領年終(沒有標準答案)。
  4. 量測資料與直方圖
    (a) 用 random.normalvariate(μ, σ) 產生 100 筆近似常態的模擬溫度資料(例如 μ=25, σ=0.2)。
    (b) 計算這 100 筆資料的平均數與標準差。
    (c) 畫出直方圖,觀察資料大致集中在哪個範圍。
    (d) 試著增加到 1000 筆資料,觀察直方圖是否更接近「鐘形曲線」。

  5. 母體 vs 樣本的差異(實驗觀察)
    (a) 先建立一個「母體」:例如用 Python 產生 10000 個均勻分布在 [0,1] 的數字。
    (b) 從這個母體中隨機抽 50 個樣本,計算樣本平均與樣本標準差。
    (c) 重複抽樣 50 次,記錄每一次的樣本平均與樣本標準差。
    (d) 用簡單圖或摘要數字,觀察樣本統計量如何圍繞著「母體」的真實平均與變異數。

  6. 加分題:Z 分數(標準化)
    對於資料中的每一個 $x$,定義 Z 分數:
    $$z = \frac{x - \bar{x}}{s}.$$
    (a) 寫一個函數 z_scores(data),回傳每筆資料的 Z 分數。
    (b) 對第 15.8 節的溫度資料計算 Z 分數,觀察哪些測量值偏離平均較多。
    (c) 思考:若某測量值的 |z| 很大(例如大於 3),你會懷疑什麼?

回首頁