All Revision Notes

COM6005 Statistical Modeling · Module 3b

Tabular Data & Chi-squared Tests

COM6005 · Module 3b · Source: Module3b_Chi-square-L02_complete.pdf (24 slides)

Contents · 7 sections

🎯 本講重點 (Learning outcomes)

  • 由 categorical data 整 one-way table(value_counts)同 two-way contingency table(pd.crosstab);用 pd.cut 將 numerical 轉 categorical。
  • 用 stacked / side-by-side bar chart 視覺化 tabular data。
  • Chi-squared test for independence:expected count Eij=ni⋅n⋅j/n⋅⋅E_{ij} = n_{i\cdot}n_{\cdot j}/n_{\cdot\cdot}、χ2\chi^2 statistic、df=(r−1)(c−1)df = (r - 1)(c - 1)、查 chi-square table、stats.chi2_contingency。
  • Chi-squared goodness-of-fit:EiE_i 由 H0H_0 嘅 distribution 計、df=K−1df = K - 1、stats.chisquare。

⭐ 考試必溫 Top-5

  1. Expected count:Eij=row total×column totalgrand totalE_{ij} = \dfrac{\text{row total}\times\text{column total}}{\text{grand total}};例:Local Math = 300 × 1000/1250 = 240。
  2. χ2=∑∑(nij−Eij)2Eij\chi^2 = \sum\sum \dfrac{(n_{ij}-E_{ij})^2}{E_{ij}};例子 χ2=55.56>5.991\chi^2 = 55.56 > 5.991 → reject independence。
  3. df:independence = (r−1)(c−1)(r - 1)(c - 1);goodness-of-fit = K−1K - 1。
  4. 查表:df=2df = 2、α=0.05\alpha = 0.05 → 5.991 = chi2.ppf(0.95, 2);df=5df = 5 → 11.071。
  5. Goodness-of-fit 朱古力例:E=100/6=16.67E = 100/6 = 16.67,χ2=8.36<11.071\chi^2 = 8.36 < 11.071,p=0.1374p = 0.1374 → do not reject(uniform)。

1. One-way 同 two-way table

Slide 3:

  • One-way table:一欄 categorical data,數每個 category 嘅 frequency。
  • Two-way (contingency) table:兩欄 categorical data,數每個 category 組合嘅 joint frequency。

Slide 4 數據(10 條 comment):

CommentRatingNumber of customers
1GoodFew
2BadFew
3GoodMany
4AverageMany
5AverageMany
6BadFew
7AverageFew
8GoodMany
9AverageMany
10BadMany
import pandas as pd
x = ["G","B","G","A","A","B","A","G","A","B"]     # Rating
y = ["F","F","M","M","M","F","F","M","M","M"]     # Number of customers (Few / Many)
freq = pd.Series(x).value_counts()                  # one-way table:A 4, G 3, B 3
joint_freq = pd.crosstab(pd.Series(x), pd.Series(y))  # two-way table

得到嘅 two-way table:

Rating \ CustomersF (Few)M (Many)Row total
A (Average)134
B (Bad)213
G (Good)123
Column total4610

1.1 Numerical → Categorical:pd.cut(slide 6)

向觀眾展示數據時,用 young / middle / senior 呢類 label 比抽象數字易明。

x = [68, 32, 47, 52, 15, 73, 67, 45, 24, 39]
age_labels = ["young", "middle", "senior"]
age_group = pd.cut(x, bins=[0, 35, 55, float('inf')], labels=age_labels)
# (0,35] → young;(35,55] → middle;(55,inf) → senior
# 結果:senior, young, middle, middle, young, senior, senior, middle, young, middle
pd.Series(age_group).value_counts()   # middle 4, young 3, senior 3
⚠️ 留意

pd.cut 預設 bins 係 右閉 (a, b]:35 歲會入 young,唔係 middle。邊界值嘅歸類係常見考點/bug。

2. Statistical graphics for tabular data

import matplotlib.pyplot as plt
ft = pd.crosstab(pd.Series(x), pd.Series(y))
ft.index.name = None
ft.columns.name = None
fig, axs = plt.subplots(2, 2, figsize=(10, 8))
ft.T.plot(kind='bar',  ax=axs[0, 0], stacked=True,  rot=0)   # 直立 stacked bar
ft.T.plot(kind='bar',  ax=axs[0, 1], stacked=False, rot=0)   # 直立 side-by-side bar
ft.T.plot(kind='barh', ax=axs[1, 0], stacked=True,  legend=False)   # 橫向 stacked
ft.T.plot(kind='barh', ax=axs[1, 1], stacked=False, legend=False)   # 橫向 side-by-side
plt.show()

Slide 8 嘅四幅圖(x 軸 F / M,顏色 A / B / G):stacked 版顯示 F 總數 4(A 1、B 2、G 1)、M 總數 6(A 3、B 1、G 2);side-by-side 版就將三個 rating 並排比較。ft.T(transpose)令 customers (F/M) 做 x 軸、rating 做顏色。

💡 Stacked vs side-by-side

Stacked 易睇每組總數同組成比例;side-by-side 易比較同一 category 喺唔同組之間嘅大細。

2.1 由 table 到 test(slide 9)

Table問題TestH0/H1H_0 / H_1
One-wayCategorical data 有冇某個 distribution pattern(例如所有 categories equally likely)?Chi-square goodness-of-fitH0H_0:符合指定 distribution;H1H_1:唔符合
Two-way兩個 categorical variables 有冇關係?Chi-square test for independenceH0H_0:independent;H1H_1:dependent

3. Chi-squared test for independence

Slides 10–11:本地生同外地生揀主修科目嘅偏好有冇分別?

  • Situation:兩欄 categorical data。
  • X = origin(Local / Foreign);Y = first subject choice(Math / Computer / Literature)。
  • Question:Is it evident that X and Y are related?
  • H0H_0:independent;H1H_1:related / dependent。

3.1 Observed 同 expected counts(slide 12)

LocalForeignSubtotals
Math25050300=nMat⋅300 = n_{Mat\cdot}
Computer40050450=nCom⋅450 = n_{Com\cdot}
Literature350150500=nLit⋅500 = n_{Lit\cdot}
Subtotals1000=n⋅Loc1000 = n_{\cdot Loc}250=n⋅For250 = n_{\cdot For}1250=n⋅⋅1250 = n_{\cdot\cdot}

Idea:如果冇 dependence,揀 Math 嘅 300 個學生應該按 Local : Foreign = 1000 : 250 嘅比例分配。Local 比例 = 1000/1250,所以 Expected Local Math = 300 × 1000/1250 = 240。

Eij=ni⋅ n⋅jn⋅⋅=row total×column totalgrand totalE_{ij} = \frac{n_{i\cdot}\, n_{\cdot j}}{n_{\cdot\cdot}} = \frac{\text{row total}\times\text{column total}}{\text{grand total}}
χ2=∑i=1r∑j=1c(nij−Eij)2Eij\chi^2 = \sum_{i=1}^{r}\sum_{j=1}^{c}\frac{(n_{ij}-E_{ij})^2}{E_{ij}}

(slide 13)如果冇 dependence,nijn_{ij} 應該接近 EijE_{ij}。χ2\chi^2 大過 critical value → dependence 證據強。Critical value 喺 chi-square table 查;建議用 p-value:p-value < α\alpha → reject “H0H_0:The two columns are independent”。

⭐ Worked example:完整手計(5 步)
  1. Hypotheses:H0H_0:origin 同 subject choice independent;H1H_1:dependent。
  2. α=0.05\alpha = 0.05。
  3. Expected counts:
    ELocalForeign
    Math300×1000/1250 = 240300×250/1250 = 60
    Computer450×1000/1250 = 360450×250/1250 = 90
    Literature500×1000/1250 = 400500×250/1250 = 100
    (檢查:每行、每欄 expected 總和 = observed 總和。)
  4. Test statistic:
    CellOE(O−E)2/E(O - E)^2/E
    Math, Local250240100/240 = 0.417
    Math, Foreign5060100/60 = 1.667
    Computer, Local4003601600/360 = 4.444
    Computer, Foreign50901600/90 = 17.778
    Literature, Local3504002500/400 = 6.25
    Literature, Foreign1501002500/100 = 25
    χ2\chi^255.56
  5. Critical value:df=(r−1)(c−1)=(3−1)(2−1)=2df = (r - 1)(c - 1) = (3 - 1)(2 - 1) = 2;α=0.05\alpha = 0.05 → 5.991。
  6. Decision:55.56 > 5.991(p=8.6×10−13<0.05p = 8.6 \times 10^{-13} < 0.05)→ reject H0H_0。結論:學生來源同主修科目選擇有關——外地生較多揀 Literature(150 vs 預期 100)、較少揀 Computer(50 vs 預期 90)。
💡 直覺理解

每格 (O−E)2/E(O-E)^2/E 係「意外程度」:差距越大、相對 expected 越大,貢獻越多。Foreign × Literature(25)同 Foreign × Computer(17.78)貢獻最大,即係 dependence 主要嚟自外地生嘅選科模式。

3.2 查 chi-square table(slides 14–15)

Slide 14 嘅 chi-square table:column = Upper Tail Areas (α\alpha),row = Degrees of Freedom;圖中右尾陰影面積 = α\alpha,左邊 1−α1 - \alpha。圈住嘅值:df=2df = 2、α=.05\alpha = .05 → 5.991。

⭐ 查表要點(slide 15)
  • Degree of freedom ν\nu(independence test)= (r−1)(c−1)(r - 1)(c - 1)。
  • α\alpha:5%(較低標準 reject H0H_0)或 1%(較高標準)。
  • 例:r=3r = 3、c=2c = 2 → df = 2;α=5%\alpha = 5\% → critical value = 5.991 = scipy.stats.chi2.ppf(0.95, 2)(chi-square distribution ν=2\nu = 2 嘅 95% quantile)。
dfα=.10\alpha = .10α=.05\alpha = .05α=.025\alpha = .025α=.01\alpha = .01
12.7063.8415.0246.635
24.6055.9917.3789.210
36.2517.8159.34811.345
47.7799.48811.14313.277
59.23611.07112.83315.086
610.64512.59214.44916.812
⚠️ 常見錯誤
  • Chi-square test 永遠係 right-tailed(χ2≥0\chi^2 \ge 0,越大越唔似 H0H_0),唔需要 α/2\alpha/2。
  • df 唔係 r×c−1r \times c - 1,係 (r−1)(c−1)(r - 1)(c - 1);r、c 唔計 subtotal 行/欄。
  • 一定要用 counts(次數),唔可以用 percentage 代入公式。
  • (補充)每格 expected count 最好 ≥5\ge 5,否則 chi-square approximation 唔可靠——slide 4 嘅 10 筆 rating 數據 expected 只有 1.2–2.4,只適合示範 code。

3.3 Python(slides 16–18)

import numpy as np
from scipy import stats
# 方法 1:直接入兩欄 raw data → 先 crosstab
contingency_table = pd.crosstab(pd.Series(x), pd.Series(y))
chi2, p, dof, expected = stats.chi2_contingency(contingency_table)
# 方法 2:直接入 joint frequency table
Ft = np.array([[250, 50], [400, 50], [350, 150]])
chi2, p, dof, expected = stats.chi2_contingency(Ft)
# Chi2ContingencyResult(statistic=55.5555, pvalue=8.635e-13, dof=2,
#   expected_freq=array([[240., 60.], [360., 90.], [400., 100.]]))
⭐ 三個等價 decision rule(slide 18)
chi2 > chi2.ppf(0.95, 2)       # statistic 大過 critical value
chi2.cdf(chi2, 2) > 0.95       # cumulative prob 大過 95%
1 - chi2.cdf(chi2, 2) < 0.05   # p-value 細過 α

1 - chi2.cdf(chi2, 2) 就係 p-value。Python 嘅 scipy.stats.chi2_contingency() 一次過做晒。

⚠️ 留意

Slide 16 寫 “In chisq.test()…”——chisq.test() 係 R 嘅函數名;Python 對應係 stats.chi2_contingency()。另外 2×2 table 時 scipy 預設做 Yates' continuity correction(correction=True),所以結果會同手計少少唔同。

4. Chi-squared goodness-of-fit

Slide 20:

  • Situation:一欄 categorical data。
  • Example:雜錦朱古力嘅顏色係咪均勻分佈(evenly distributed)?
  • Question:Is it evident that the distribution of (yellow, red, orange, brown, blue, green) is not even?
  • H0H_0:The distribution is even,即 (1/6, 1/6, 1/6, 1/6, 1/6, 1/6)。H1H_1:The distribution is not even (uniformly distributed)。
  • Experiment:買一包嚟數。
YellowRedOrangeBrownBlueGreenTotal
20 (n1n_1)13 (n2n_2)12 (n3n_3)12 (n4n_4)18 (n5n_5)25 (n6n_6)100
Ei=n×pi,χ2=∑i=1K(ni−Ei)2Ei,df=K−1E_i = n \times p_i, \qquad \chi^2 = \sum_{i=1}^{K}\frac{(n_i-E_i)^2}{E_i}, \qquad df = K-1
⭐ Worked example:朱古力顏色(slides 21–23)
  1. Hypotheses:H0H_0:6 種顏色各佔 1/6;H1H_1:唔係均勻。
  2. α=0.05\alpha = 0.05。
  3. Expected:uniform → 每色 Ei=100/6=16.67E_i = 100/6 = 16.67。
  4. Test statistic:
    ColourOE(O−E)2/E(O - E)^2/E
    Yellow2016.670.667
    Red1316.670.807
    Orange1216.671.307
    Brown1216.671.307
    Blue1816.670.107
    Green2516.674.167
    χ2\chi^28.36
  5. Critical value:df=K−1=6−1=5df = K - 1 = 6 - 1 = 5;α=0.05\alpha = 0.05 → 11.071(slide 22 圈住)。
  6. Decision:8.36 < 11.071(p-value = 0.1374 > 0.05)→ H0H_0 is not rejected。結論(slide 23):We cannot statistically reject the null hypothesis that the distribution is uniform。
from scipy import stats
obs = [20, 13, 12, 12, 18, 25]
stats.chisquare(obs)                          # 預設 expected = 平均分配
# Power_divergenceResult(statistic=8.36, pvalue=0.1374)
stats.chisquare(obs, f_exp=[100/6]*6)         # 明確指定 expected
stats.chi2.ppf(0.95, 5)                       # 11.071
1 - stats.chi2.cdf(8.36, 5)                   # p-value 0.1374

Slide 24:同樣三個等價 rule(df=5df = 5):chi2 > chi2.ppf(0.95, 5) ⇔ chi2.cdf(chi2, 5) > 0.95 ⇔ 1 - chi2.cdf(chi2, 5) < 0.05;Python 用 stats.chisquare()。

⚠️ 常見錯誤
  • Goodness-of-fit df=df = K−1K - 1(類別數 − 1),唔係 (r−1)(c−1)(r - 1)(c - 1)。
  • H0H_0 唔一定係 uniform:例如 H0H_0 可以係 (0.3, 0.2, 0.2, 0.1, 0.1, 0.1),咁 Ei=100×piE_i = 100 \times p_i,要用 f_exp= 指定。
  • “Not rejected” ≠ 「證明係 uniform」,只係冇足夠證據話唔係。

5. Independence vs Goodness-of-fit 比較

⭐ 對照表
Test for independenceGoodness-of-fit
數據兩欄 categorical(two-way table)一欄 categorical(one-way table)
H0H_0兩個 variables independent數據符合指定 distribution(例如 uniform)
ExpectedEij=ni⋅n⋅j/n⋅⋅E_{ij} = n_{i\cdot}n_{\cdot j}/n_{\cdot\cdot}Ei=npiE_i = n p_i
Statistic∑∑(nij−Eij)2/Eij\sum\sum (n_{ij}-E_{ij})^2/E_{ij}∑(ni−Ei)2/Ei\sum (n_i-E_i)^2/E_i
df(r−1)(c−1)(r - 1)(c - 1)K−1K - 1
Pythonstats.chi2_contingency(table)stats.chisquare(obs, f_exp)
Slide 例子Origin × Subject:χ2=55.56\chi^2 = 55.56,df=2df = 2,crit 5.991 → reject朱古力顏色:χ2=8.36\chi^2 = 8.36,df=5df = 5,crit 11.071 → not reject
🖼️ 圖片內容

Slide 10 係「本地生 vs 外地生」嘅示意圖頁,冇額外文字;slides 2、19 係分節標題頁。

自我測驗 Self-test

Q1. 2×2 table:男 吸煙 30、不吸煙 70;女 吸煙 20、不吸煙 80。求所有 expected counts。

Row totals:男 100、女 100;column totals:吸煙 50、不吸煙 150;N=200N = 200。E(男, 吸煙) = 100 × 50/200 = 25;E(男, 不吸煙) = 75;E(女, 吸煙) = 25;E(女, 不吸煙) = 75。

Q2. 繼續 Q1:計 χ2\chi^2(不用 continuity correction),df = ?,α=0.05\alpha = 0.05 結論?

(30−25)2/25=1(30-25)^2/25 = 1;(70−75)2/75=0.333(70-75)^2/75 = 0.333;(20−25)2/25=1(20-25)^2/25 = 1;(80−75)2/75=0.333(80-75)^2/75 = 0.333;χ2=2.667\chi^2 = 2.667。df=(2−1)(2−1)=1df = (2-1)(2-1) = 1,critical 3.841。2.667 < 3.841 → do not reject:冇足夠證據顯示性別同吸煙有關。

Q3. 一個 4×3 contingency table 嘅 df 係幾多?α=0.01\alpha = 0.01 critical value?

df=(4−1)(3−1)=6df = (4 - 1)(3 - 1) = 6;α=0.01\alpha = 0.01 → 16.812。

Q4. 骰子擲 60 次:1–6 點分別出現 8, 9, 12, 11, 6, 14 次。用 α=0.05\alpha = 0.05 檢驗骰子是否公平。

E=10E = 10。χ2=(4+1+4+1+16+16)/10=4.2\chi^2 = (4 + 1 + 4 + 1 + 16 + 16)/10 = 4.2。df=5df = 5,critical 11.071。4.2 < 11.071 → do not reject:冇證據顯示骰子唔公平。

Q5. 某品牌聲稱顏色比例係 Red 40%、Blue 30%、Green 30%。抽 200 粒:Red 95、Blue 50、Green 55。寫 expected 同 χ2\chi^2。

E=80,60,60E = 80, 60, 60。χ2=225/80+100/60+25/60=2.8125+1.6667+0.4167=4.896\chi^2 = 225/80 + 100/60 + 25/60 = 2.8125 + 1.6667 + 0.4167 = 4.896。df=2df = 2,critical 5.991 → do not reject。Python:stats.chisquare([95,50,55], f_exp=[80,60,60])。

Q6. 寫出三個等價嘅 decision rule(df = 2,α=0.05\alpha = 0.05)。

chi2 > chi2.ppf(0.95, 2);chi2.cdf(chi2, 2) > 0.95;1 - chi2.cdf(chi2, 2) < 0.05。

Q7. pd.cut([35, 55, 56], bins=[0, 35, 55, float('inf')], labels=["young","middle","senior"]) 結果係咩?

young, middle, senior(bins 右閉:35∈(0,35]35 \in (0,35],55∈(35,55]55 \in (35,55],56∈(55,∞)56 \in (55,\infty))。

Q8. 點解 chi-square test 唔分 one-tailed / two-tailed?

χ2\chi^2 係平方和,永遠 ≥0\ge 0;任何方向嘅偏離(O>EO > E 或 O<EO < E)都會令 χ2\chi^2 變大,所以 rejection region 只喺右尾。

一頁總結 Cheat sheet

⭐ 考前速記
  • One-way table:pd.Series(x).value_counts();two-way:pd.crosstab(x, y);binning:pd.cut(x, bins, labels)(右閉)。
  • Plot:ft.T.plot(kind='bar'/'barh', stacked=True/False)。
  • Independence:H0H_0 independent;Eij=row×colNE_{ij}=\frac{\text{row}\times\text{col}}{N};df=(r−1)(c−1)df = (r - 1)(c - 1);chi2_contingency。
  • Goodness-of-fit:H0H_0 指定 distribution;Ei=npiE_i = np_i;df=K−1df = K - 1;chisquare。
  • χ2=∑(O−E)2/E\chi^2=\sum (O-E)^2/E;永遠 right-tailed;用 counts。
  • Critical:df 1 → 3.841|df 2 → 5.991|df 5 → 11.071(α=0.05\alpha = 0.05);chi2.ppf(0.95, df)。
  • p-value = 1 - chi2.cdf(stat, df);p<αp < \alpha → reject。
  • 例 1:Local/Foreign × Math/Computer/Lit:E=240/60,360/90,400/100E = 240/60, 360/90, 400/100;χ2=55.56\chi^2 = 55.56 → reject(dependent)。
  • 例 2:朱古力 6 色:E=16.67E = 16.67;χ2=8.36\chi^2 = 8.36、p=0.1374p = 0.1374 → not reject(uniform)。