卡方檢定一篇看懂,白話介紹三種檢定方式

by 好豪
Published: Updated:

卡方檢定(Chi-squared Test)是分析類別型資料的統計方法,用來評估類別變數之間的關聯性,在許多領域包括商業、社會科學、醫藥衛生等等都有其應用,卡方檢定能回答的問題像是:

  • 性別跟政黨支持度是否有關?
  • 不同類型的流感疫苗,預防染疫的效果是否不同?
  • A/B 測試:網頁上新版本的按鈕,是否比舊版本有更高的點擊率?

學習卡方檢定的困難點在於,學校的統計課教卡方檢定的時候,難免充斥一大堆統計學名詞,卡方分配、自由度、統計量等等,數學公式又落落長,容易學得暈頭轉向。但,卡方檢定在資料科學實戰中其實超級好用!沒有好好學會實在很可惜。

這則資料科學筆記的目標是不講數學公式,完全用白話與範例介紹卡方檢定,讓它不再晦澀難解。以下將先帶你認識對類別型資料分析超重要的列聯表,接著介紹三種最常見的卡方檢定(配適度、獨立性、同質性檢定),最後也說明在 Python 該如何進行卡方檢定。

希望看完這篇文章後,你會感受到卡方檢定的威力,並能夠立即將它 應用在實戰中



列聯表資料

我認為,光是理解什麼是列聯表,卡方檢定就已經學會一半了 (*゚▽゚*)

列聯表(Contingency Table)是用來呈現不同類別出現頻率的表格型態資料,它幫助你有組織地呈現類別型資料CCategorical Data)、以看出變數之間的關聯。列聯表區分成兩種類型:

單因子(One-way)列聯表,用來呈現一個類別變數的各類出現頻率。例如利用職業這個類別變數,要觀察某個遊戲 APP 設計團隊裡面的分工,會呈現單因子列聯表如下:

軟體工程師資料科學家產品經理美術設計
4 人1 人3 人4 人

二因子(Two-way)列聯表,呈現兩個類別變數的各類出現頻率,二因子列聯表在英文又稱為 Cross-Tabulation 或 Crosstabs。例如,利用職業加上產品類型這兩個變數,我會用以下二因子列聯表來了解「公司內的不同產品類型,團隊內的職業分工是否不同?」:

軟體工程師資料科學家產品經理美術設計
遊戲 APP4 人1 人3 人8 人
筆記 APP9 人2 人4 人2 人
鬧鐘 APP2 人0 人1 人2 人

光是看到以上這個二因子列聯表,你應該不用統計檢定,也會做出「產品類型與職業分工的人數頻率分佈存在關聯」這個結論吧!舉例而言,資料裡看出遊戲 APP 需要特別多美術設計專家,筆記與鬧鐘 APP 需要的美術設計相對較少。

接下來將介紹的三種卡方檢定,會進一步看出單因子與二因子列聯表的不同用途。


卡方檢定,以及它的三種檢定方式

不論是統計學課本或實戰應用,我們常看到卡方檢定分成三種:配適度檢定、同質性檢定、以及獨立性檢定。實際上,它們背後都是 同一個檢定方法,只是用途不同而已!

卡方檢定的目標是檢驗你實際觀察到出現頻率數據
是否與你預期看到的不一樣?

筆者好豪認為,只要記得卡方檢定的關鍵是實際「觀察」到的資料與「預期」看到的資料比較,學習以下三種檢定時,就只需要注意問題假設的差別即可,絕不會難懂!


配適度檢定

配適度檢定(Goodness-of-fit Test,又稱適合度檢定)用來比較某個事物的出現頻率分佈是否符合研究者所宣稱的分佈。換言之,你預想類別資料應該要是某個比例關係、你會先明確寫下這個數字,實際拿到資料後,配適度檢定將幫你檢查資料內的比例關係是否跟你事先寫下的比例數字一模一樣。

配適度檢定:檢驗你預期的出現頻率分佈,是否「適合」用來描述你實際拿到的資料

配適度檢定建立的假設如下:

  • 虛無假設 H0:數據符合特定出現頻率分佈
  • 對立假設 H1:數據不符合特定出現頻率分佈

一個簡單的例子,我的常識告訴我,男生與女生出生的機率是相同的,所以,我猜想台北市的男性與女性人口數應該是 1:1。我接著要問的問題也很簡單,我取得台北市男女性人口數 資料 後,將會用以下的單因子列聯表來呈現:

男性女性
127.3 萬人139.5 萬人

卡方檢定是「觀察」數據與「預期」數據的比較,列聯表呈現出我們觀察到的數據了,那預期數據是什麼呢?正是我自己相信的 1:1 這個數字。以上資料,台北市總人口數是 127.3 萬 + 139.5 萬 = 266.8 萬 人,而我預期男女比應該要是 1:1,所以預期男女人口數都會是 266.8 萬 / 2 = 133.4 萬人

男性女性
觀察資料127.3 萬人139.5 萬人
預期資料133.4 萬人133.4 萬人

現在看到男女性人口數實際資料都跟我預期看到 1:1 的有落差,這個落差到底是否顯著呢?只要把以上的單因子表格交給統計軟體,就能知道囉。


同質性檢定

同質性檢定(Test of Homogeneity,又稱齊一性檢定)檢驗資料的不同子群體、是否在某個類別變數有不同的出現頻率分佈。再白話地說,是在檢驗資料分成好幾群之後,它們的比例關係是否相同(同質)。

同質性檢定:檢驗對於同一個類別變數,資料內不同群體的出現頻率分佈是否相同

同質性檢定建立的假設如下:

  • 虛無假設 H0:對於某一類別資料,不同子群體之間存在相同的出現頻率分佈
  • 對立假設 H1:對於某一類別資料,不同子群體之間存在不同的出現頻率分佈

此檢定會用一個類別變數來區別子群體、再用另一個變數作為出現頻率研究目標,共有兩個類別變數,因此,需要用到二因子列聯表

同質性檢定的運用場景範例包括:

  • 不同國家的有無抽煙比例是否相同
  • 在美國,不同教育程度的民主黨/共和黨/無黨籍比例是否相同
  • 不同性別,養貓/養狗/養兔子/不養寵物的比例是否相同
    • (嘿,這超重要!如果可以用資料證明男性養兔子的比例特高,下次我跟兄弟出去喝酒終於可以試著聊兔子,不要每次都聊股票或政治!)

而在此,筆者好豪還想以我的資料科學工作超常遇到的 A/B Test 案例來舉例。假設你設計了一個購物網站,其中有一個購買按鈕,想透過 A/B Test 來測試新的按鈕樣式會不會讓人更想點擊,而你總共設計了 4 個新樣式、想要跟舊樣式比較點擊率。你將用戶隨機分成 5 群、執行 A/B Test 之後,會有以下兩個類別資料:

  • 樣式(子群體):1/5 的用戶看到舊的按鈕,1/5 的用戶看到新樣式 A,1/5 的用戶看到新樣式 B,以此類推
  • 點擊(研究目標):有點擊按鈕的用戶人數、沒有點擊按鈕的用戶人數

進行了總共 5,000 位用戶的實驗後,會搜集到的二因子列聯表如下:

舊樣式新樣式 A新樣式 B新樣式 C新樣式 D
沒點擊按鈕700 人698 人688 人701 人600 人
有點擊按鈕300 人302 人312 人299 人400 人

再一次,我們來看看這跟卡方檢定的「觀察」與「預期」比較方法有什麼關係。當然,上方這個列聯表正是我們的實際觀察資料了,那麼,我們的預期是什麼呢?再複習一下同質性檢定的假設,虛無假設是「每個樣式的點擊與不點擊比例相同」,因此,我們的「同質性預期」可以用人數加總來取得:

  • 沒點擊按鈕的用戶,總共有 700 + 698 + 688 + 701 + 600 = 3,387 人
  • 有點擊按鈕的用戶,總共有 300 + 302 + 312 + 299 + 400 = 1,613 人
  • 如果每種樣式,有無點擊按鈕的比例都一樣的話,那這個點擊率的預期會是 1,613 / (1,613 + 3,387) = 32.3%

把以上列聯表資料交給統計軟體(例如本文後半介紹的 Python),卡方檢定會做的事情是幫你回答:「這 5 種按鈕樣式,是否點擊率全都一樣是 32.3%?」。在範例中,舊樣式還有新樣式 A ~ D 的點擊率都很接近 32.3%,只有新樣式 D 一支獨秀是點擊率 40%,那我們就可以猜測卡方檢定很有可能會拒絕虛無假設,認為這些樣式的點擊率不是全都相同。

我在實戰的 A/B 測試場景,如果跟此案例一樣,實驗有超過兩種變化(分成 A/B/C/D/E 多組),卡方的同質性檢定總會是我的首選,因為這個方法避免了多重檢定問題。要比較多種不同按鈕樣式的點擊率,反覆做 t-Test 也是一種選項,樣式 A 跟舊樣式 t-Test、樣式 B 也跟舊樣式 t-Test、以此類推,然而,這種做法在實驗組別很多的時候會使偽陽性錯誤大大提升,若想多了解此類分析偏誤,請參考我寫過的統計學教學《多重檢定問題:一定會有人中樂透》

關於同質性檢定的觀念,筆者再囉唆補充兩點:

  • 前述的配適度檢定要事先宣告比例的數字是什麼,同質性檢定不用宣告
  • 同質性檢定只比較各子群體的比例是否相同,如果最後拒絕虛無假設、證明出不同,我們並不知道各子群體比例是誰高誰低

獨立性檢定

相對於前兩個檢定,卡方的獨立性檢定(Test of Independence)的定義相對好解釋:

獨立性檢定:檢驗兩個類別變數有沒有關聯性
若沒有關聯,表示兩類別變數彼此獨立

獨立性檢定建立的假設如下:

  • 虛無假設 H0:兩個類別變數彼此獨立(無關聯性)
  • 對立假設 H1:兩個類別變數不是彼此獨立(存在關聯性)

適用情境例如:

  • 宗教信仰類型與施打流感疫苗比例是否有關聯
  • 身高是否超過 170 公分與是否喜歡打籃球的關聯性
  • 居住縣市與支持政黨的關聯性

我覺得獨立性檢定的「有沒有關聯」問題,用條件機率比較好理解。以上述的「縣市」與「政黨支持度」兩變數關聯性為例,假設我已經知道全台灣人對政黨A的支持率是 40%,再假設我們只聚焦台北市與桃園市:

  • 兩變數獨立(無關聯)
    • 已知政黨A支持率全台灣平均是 40%
    • 假設後來得知,台北市與桃園市對政黨A支持率都是 40%
    • 表示縣市的資訊對於政黨支持度沒有貢獻,兩變數無關聯
  • 兩變數不獨立(存在關聯)
    • 同樣,已知政黨A支持率全台灣平均是 40%
    • 假設後來得知,台北市對政黨A支持率是 60%,桃園市則是 25%
    • 表示政黨支持度取決於縣市的資訊,兩變數有關聯

整理比較

目前為止,文章介紹完了卡方的三種檢定,再次強調,它們背後都是同一個檢定方法、檢定步驟 都一樣,只有用途不同,或者說,思考問題的角度不同。

這幾個檢定有其中兩項異同,我認為值得特別提出。

首先,只有配適度檢定需要在檢定開始前決定出某個「已知分佈」。這個已知分佈可能是來自研究者自己預期的空口白話、也可能來自過去經驗得知的理論分佈。只有配適度檢定要在假設中就白紙黑字寫下某個比例數字,配適度檢定會看實際資料的比例分佈是不是符合這個數字。其他兩種檢定不需要預先寫出這個已知分佈。

第二,同質性檢定跟獨立性檢定兩者幾乎相同,是一體兩面的思考方式,這兩者最好的分辨方式是「是否同一群體」的分析設計問題。我們沿用正上方的「縣市」與「政黨支持度」資料案例:

  • 同質性檢定檢驗不同子群體在某類別變數的比例分佈是否不同
    • 是否同一群體:,資料來自不同群體
      • 「縣市」不同,即代表不同群體
    • H0:對於「是否支持某政黨」類別資料,不同「縣市」子群體之間存在相同的比例分佈
    • H1:對於「是否支持某政黨」類別資料,不同「縣市」子群體之間存在不同的比例分佈
  • 獨立性檢定檢驗兩類別變數關聯性
    • 是否同一群體:,資料來自同一群體
      • 即使「縣市」不同,仍都是「台灣人」群體
    • H0:「是否支持某政黨」與「縣市」兩變數彼此獨立(無關聯性)
    • H1:「是否支持某政黨」與「縣市」兩變數不是彼此獨立(存在關聯性)
範例:同質性檢定跟獨立性檢定的差異
(製圖:好豪)

在此範例中,兩項檢定使用的資料一模一樣、背後的卡方檢定運算也一模一樣,最後算出的 P-value、以及得到是否顯著的結論也是一模一樣,解決的目標問題大方向也相同,只有思考的角度稍稍不同。

即使同質性檢定跟獨立性檢定差異如此細微,分析邏輯的不同仍必須好好理解,實戰的時候才得以用正確的邏輯來解釋自己的分析流程。

以下是上述三種卡方檢定差異的簡單表格整理,幫助你快速複習卡方檢定的觀念:

三種卡方檢定整理比較
(製圖:好豪)


Python 卡方檢定介紹

Google 搜尋 Python 的卡方檢定執行方法,幾乎都會找到 scipy 套件內的兩個函式:chisquare()chi2_contingency(),這兩個函式用途不同,認識單因子與二因子兩種列聯表的差別之後,要辨別這兩個函式超級容易!

  • scipy.stats.chisquare():用於配適度檢定,輸入為單因子列聯表
  • scipy.stats.chi2_contingency():用於同質性獨立性檢定,輸入為二因子列聯表

scikit-learn 套件裡有長得很像的 chi2() 函式,它是特別用在特徵選擇的,用法請參考 這一篇

先從配適度檢定的 chisquare() 開始介紹,沿用前面配適度檢定的小節使用過的台北市男女性人口分佈範例,已知台北市總人口數是 266.8 萬人,我想檢驗的虛無假設是「台北市男女性人口數為 1:1」。

男性女性
觀察資料127.3 萬人139.5 萬人
預期資料133.4 萬人133.4 萬人

配適度檢定需要明確寫出我們心中假設的出現頻率分佈數字,此例中是「1:1」,轉換成絕對數字(人數)後、寫在函式裡的 f_exp 引數;而觀察到的資料則寫在 f_obs 引數。

>>> import numpy as np
>>> from scipy import stats

>>> stats.chisquare(
...     # f_ops: 實際觀察的數據
...     f_obs = np.array([127.3, 139.5]), 
...     # f_exp: 預期觀察到的數據
...     f_exp = np.array([133.4, 133.4])
... )
Power_divergenceResult(
    statistic=0.5578710644677664, 
    pvalue=0.4551192970305098)

得到的 P 值大於 0.05,無法拒絕虛無假設,因此結論「台北市男女性人口數為 1:1」。


同質性檢定與獨立性檢定都是使用 scipy.stats.chi2_contingency(),在此就用方才同質性檢定用到的 A/B Test 範例來介紹吧。同質性與獨立性檢定都是使用二因子列聯表,函式需要輸入二因子列聯表到 observed 引數

舊樣式新樣式 A新樣式 B新樣式 C新樣式 D
沒點擊按鈕700 人698 人688 人701 人600 人
有點擊按鈕300 人302 人312 人299 人400 人
>>> import numpy as np
>>> from scipy import stats

>>> stats.chi2_contingency(
...     observed = np.array([
...         [700, 698, 688, 701, 600], # 沒點擊按鈕人數
...         [300, 302, 312, 299, 400]  # 有點擊按鈕人數
...     ])
... )
Chi2ContingencyResult(
    statistic=34.755989633240844, 
    pvalue=5.213517903848745e-07, 
    dof=4, 
    expected_freq=array([[677.4, 677.4, 677.4, 677.4, 677.4],
       [322.6, 322.6, 322.6, 322.6, 322.6]]))

函式輸出 P 值遠小於 0.05,在同質性檢定的角度我們會結論「不是每個按鈕樣式點擊率都一樣」,而在獨立性檢定的角度我們會結論「按鈕樣式與點擊率存在關聯」。

scipy.stats.chi2_contingency() 輸出的其他內容也值得我們注意:

  • dof自由度(Degree of Freedom),在二因子列聯表 dof = (行數-1)*(列數-1
    • 此例為 (2-1) * (5-1) = 4
  • expected_freq:如果各個子群體真的「同質」,那麼頻率分佈應該長什麼樣子
    • 此例數字跟上方小節算過的一樣是:有點擊 1,613 人 / (全部人數 1,613 + 3,387 人) = 32.26%

結語

需要分析類別型資料時,卡方檢定是強大的統計工具,只要搞懂它的用途與假設,不用死背數學公式,卡方檢定既方便實作、也容易解釋。這則資料科學筆記,我盡力不用數學、而是用白話與資料範例介紹三種卡方檢定:

  • 配適度檢定:在單因子列聯表檢驗特定出現頻率分佈是否適合用來描述數據
  • 同質性檢定:在二因子列聯表檢驗各組數據的比例關係是否相同
  • 獨立性檢定:在二因子列聯表檢驗兩個類別型變數是否存在關聯

在 Python 知名的 scipy 套件使用 scipy.stats.chisquare()scipy.stats.chi2_contingency() 這兩個函式,以上三種卡方檢定都非常容易實作。

如果你想對卡方檢定與類別型資料分析有更進一步認識,特別推薦你繼續閱讀筆者的以下文章:

相信用心看完這些資料科學筆記的你,已經學會怎麼把卡方檢定應用在資料科學實戰中!


參考資料:

data-science-practical-statistics


如果這篇文章有幫助到你,歡迎追蹤好豪的 Facebook 粉絲專頁Threads 帳號,我會持續分享重要的統計學知識與學習心得;也可以點選下方按鈕,分享給對資料科學有興趣的朋友們。

推薦閱讀