卡方檢驗是假設檢驗的一種,用於分析兩個類別變量的相關關係,是一種非參數假設檢驗,得出的結論無非就是相關或者不相關,因此有的教材上又叫「獨立性檢驗」,因此若是不是很清楚假設檢驗的朋友們,要好好複習一下假設檢驗了。提起假設檢驗,會扯出一堆東西,這裏我簡單爲你們梳理一下。python
類別變量就是取值爲離散值的變量,「性別」就是一個類別變量,它的取值只有「男」和「女」,相似還有」婚否「、」國籍「等。面試
卡方檢驗用於分析兩個類別變量的相關關係,這是什麼意思呢?以咱們熟知的 Kaggle 平臺上的泰坦尼克號倖存者預測提供的數據爲例,」性別「對於」是否倖存「的關係研究,就屬於這方面的內容。研究代表,泰坦尼克號上的乘客秉承」女士優先,照顧弱勢羣體「的基本原則,所以女性倖存的機率比男性要大,這就說明,」性別「對於」是否倖存「有相關關係,咱們後面會使用卡方檢驗來驗證這一事實。app
假設檢驗,顧名思義,就是提出一個假設,而後檢驗你提出的假設是否正確。假設檢驗的流程實際上是固定的,關鍵其實在於理解假設檢驗的設計原則。函數
那麼咱們假設什麼呢?這裏就要引入「原假設」和「備擇假設」的概念了,「原假設」是「備擇假設」的對立面。下面這個原則很重要:測試
備擇假設一般是研究者想收集證據予以支持的假設。原假設是研究者想收集證據予以推翻的假設。spa
重要的事情,我再寫兩遍:若是你想經過種種論證,證實一件事情,就要把這件事情寫成「備擇假設」。備擇假設一般用於表達研究者本身傾向於支持的見解(這很主觀),而後就是想辦法收集證據拒絕原假設,以支持備擇假設。設計
特別要說明的一點是:若是你不遵照這個「原假設」和「備擇假設」設計的基本原則,你極可能會獲得相反的結論。code
假設檢驗很像司法界對於一個事實的認定,本着「疑罪從無」的原則,若是你要說明一我的有罪,你必須提供充足的證據,不然被告人的罪名就不能成立,這個說法叫「沒有充分的證據證實被告有罪」。blog
所以,若是咱們最後的結論是「原假設」成立,咱們通常不這麼說,即咱們不說「原假設」成立,咱們不說「原假設」是真的。咱們說不能拒絕「原假設」,或者說沒有充分的證據拒絕「原假設」,或者說沒有充分的證據證實「備擇假設」成立。教程
由於咱們作假設檢驗必定是以爲兩個類別變量有關係,纔去作檢驗。再想一想那個「疑罪從無」原則,咱們是以爲一我的有罪,纔去舉證。所以卡方檢驗的「原假設」必定是假設獨立,「備擇假設」必定是假設相關,即:
原假設:類別變量 \(A\) 與類別變量 \(B\) 獨立
備擇假設:類別變量 \(A\) 與類別變量 \(B\) 不獨立
這一點應該是極其明確的,咱們的統計軟件中都是這樣設定的。
作「檢驗」這件事情,就很像咱們之前作的「反證法」,咱們假定要證實的結論的對立面成立,而後推出矛盾,即說明了咱們的假設是錯誤的,即原命題成立。請看下面這個例子:
請你證實:這個餐廳的菜很難吃。
證實:假設這個餐廳的菜很好吃,那麼週末的晚上生意必定很好,然而實際觀察下來,顧客流量和平時同樣,推出矛盾,因此假設不成立,即這個餐廳的菜很難吃。
用假設檢驗的思路,在這個例子中:
原假設:這個餐廳的菜很好吃;
備擇假設:這個餐廳的菜很難吃。
咱們把傾向於要證實的結論設置爲「備擇假設」,而推理是基於「原假設」成立進行的,推理得出矛盾,說明「原假設」錯誤,從錯誤的起點推出了錯誤的結論,所以「原假設」不成立,這就是假設檢驗裏面說的「拒絕原假設」。
所以,檢驗其實很簡單,就是一個是非論證的過程,是單選題,只有兩個選項,選擇其一。
假設檢驗的論證實際上是固定的,就是基於「小几率事件在一次試驗中幾乎不可能發生」,一般,咱們獲得的矛盾就在於:
經過計算統計量,發現經過一次試驗獲得這個統計量是一個「小几率事件」,「小几率事件」在一次試驗中,竟然發生了,咱們就認爲這是很「詭異」的,必定是以前的某個環節出了問題,即「原假設」不成立,因而拒絕「原假設」,即證實了「備擇假設」成立。
「卡方分佈」(也寫做 「\(\chi^2 分佈\)」)是統計學領域的三大分佈之一,另外兩個分佈是「\(t\) 分佈」與「\(F\) 分佈」,這些分佈都是由正態分佈推導出來的,能夠認爲它們是咱們熟知的分佈,由於它們能夠取哪些值,以及取這些值的機率都是徹底弄清楚了的。
統計學的研究任務是經過樣本研究整體,由於咱們沒法把全部的整體都作一次測試,通常可行的作法就是從整體中抽取一部分數據,根據對這一部分數據的研究,推測整體的一些性質。
而「三大分佈」就是咱們研究樣本的時候選取的參照物。通常咱們研究的思路是這樣的:若是通過分析,得出待研究的樣本符合這些咱們已知的分佈之一,由於三大分佈是被咱們的統計學家徹底研究透了的,能夠認爲是無比正確的,就能夠經過查表獲得這些分佈的信息,進而獲得樣本的一些性質,幫助咱們決策。
這裏舉一個例子,好比你是一個面試官,你手上掌握着「北京」、「上海」、「廣州」三個省市的人才信息庫(至關於上面咱們說的統計學的三大分佈),來了一個面試者,從簡歷中得知這我的來自「北京」,那麼咱們就能夠直接從「北京」市的人才信息庫中查閱到他的詳細履歷,掌握到他更全面的信息。
作假設檢驗的時候,咱們也是相似的思路,咱們須要利用整體的樣本構造出合適的統計量(或樞軸量),並使其服從或近似地服從已知的肯定分佈,這樣咱們就能夠查閱這些肯定分佈的相關信息,獲得待研究樣本所反映出來的整體的一些性質。
上面說到了「統計量」和「樞軸量」,下面簡單談一談。
統計量:不含整體分佈未知參數的函數稱爲樣本的統計量。
統計量常常做爲一個樣本的表明,例如平均數、衆數、最大值、最小值,統計量由多個數映射成一個數。
樞軸量:僅含有一個未知參數,而且分佈已知的樣本的函數,稱爲樞軸量。
樞軸量的思想其實就是解方程,或者說解不等式,這一部分很是重要的理論基礎是「抽樣分佈定理」。若是忘記了的朋友們必定要翻翻之前的教程,「抽樣分佈定理」是很是重要的。根據抽樣分佈定理,咱們常常是這樣用的:樣本的某個含有未知參數的函數符合某個已知分佈,已知分佈能夠查表,所以未知參數的性質就知道了。求「置信區間」與作「假設檢驗」一般就是這樣的思路。
\[ \chi^2=\sum\sum \frac{(f_o-f_e)^2}{f_e} \]
說明:\(f_o\) 是觀測頻數(實際值),\(f_e\) 是指望頻數(能夠認爲是理論值),指望頻數的計算公式咱們立刻會介紹到。這個統計量服從自由度爲 \((r-1)(c-1)\) 的 \(\chi^2\) 分佈,\(r\) 爲行數,\(c\) 爲列數。
這裏必定要舉例才能說清楚了:
如下內容摘抄自中國人民大學龍永紅主編《機率論與數理統計》(第三版)P190 「獨立性檢驗」一節例 5.32。
研究青少年行爲與家庭情況的關係,調查結果以下:
青少年行爲\家庭情況 | 離異家庭 | 和氣家庭 | 合計 |
---|---|---|---|
犯罪 | \(178\) | \(272\) | \(450\) |
未犯罪 | \(38\) | \(502\) | \(540\) |
合計 | \(216\) | \(774\) | \(990\) |
分析:「青少年行爲」是離散型變量,有「犯罪」與「未犯罪」兩個取值;「家庭情況」是也離散型變量,有「離異家庭」與「和氣家庭」兩個取值,從直覺上,咱們認爲它們是相關的。所以
第 1 步:創建統計假設。
原假設:「青少年行爲」與「家庭情況」獨立。
備擇假設:「青少年行爲」與「家庭情況」不獨立。
第 2 步:計算指望頻數與檢驗統計量。
要計算出檢驗統計量,關鍵是計算出指望頻數。咱們以前說到了,假設檢驗是基於原假設進行論證,所以,咱們的指望頻數應該是基於【「青少年行爲」與「家庭情況」獨立】獲得的。所以有:
兩個類別的交叉項的機率能夠根據獨立事件的機率乘法公式獲得。具體是這樣作的,從上面那張表中:
在【「青少年行爲」與「家庭情況」獨立】這個假設下有:
\[ P(「犯罪」而且「離異家庭」) = P(犯罪) \times P(離異家庭) = \cfrac{450}{990} \times \cfrac{216}{990} \]
\[ P(「犯罪」而且「和氣家庭」) = P(犯罪) \times P(和氣家庭) = \cfrac{450}{990} \times \cfrac{774}{990} \]
\[ P(「未犯罪」而且「離異家庭」) = P(犯罪) \times P(離異家庭) = \cfrac{540}{990} \times \cfrac{216}{990} \]
\[ P(「未犯罪」而且「離異家庭」) = P(犯罪) \times P(離異家庭) = \cfrac{540}{990} \times \cfrac{774}{990} \]
咱們要計算指望頻數,就把上面這 \(4\) 個機率分別乘以樣本總數 \(990\) 就能夠了:
青少年行爲\家庭情況 | 離異家庭 | 和氣家庭 |
---|---|---|
犯罪 | \(450\times \frac{216}{990} \approx 98.18\) | \(450 \times \frac{774}{990} \approx 351.82\) |
未犯罪 | \(540 \times \frac{216}{990} \approx 117.82\) | \(540 \times \frac{774}{990} \approx 422.18\) |
下面將每一個單元格的 \(\frac{(f_o-f_e)^2}{f_e}\) 加起來,就能夠獲得 \(\chi^2\) 統計量:
\[ \begin{aligned} \chi^2 &= \cfrac{(178-98.18)^2}{98.18} + \cfrac{(272-351.82)^2}{351.82} + \cfrac{(38-117.82)^2}{117.82} + \cfrac{(502-422.18)^2}{422.18} \\ & \approx 64.89 + 18.11 + 54.06 + 15.09 \\ & \approx 152.15 \end{aligned} \]
上面說服從自由度爲 \((r-1)(c-1)\) 的 \(\chi^2\) 分佈,\(r\) 爲行數,\(c\) 爲列數,即服從 \((2-1)\times (2-1) = 1\) 的 \(\chi^2\) 分佈,接下來,咱們就要看獲得這個統計量的機率有多大:
from scipy import stats import seaborn as sns import matplotlib.pyplot as plt samples = stats.chi2.rvs(size=10000, df=1) sns.distplot(samples) plt.title('$\chi^2$,df=1') plt.show()
獲得圖像以下:
能夠看到,\(152.15\) 都不在能圖像顯示到的範圍以內,說明這個機率很低。下面咱們或者使用 Python 查一下,這個機率是多少:
from scipy import stats stats.chi2.pdf(152.15, df=1)
獲得:\(2.956796099836173e-35\),確實是一個幾乎爲 \(0\) 的數。這說明了什麼呢?
說明了,在咱們的假設【「青少年行爲」與「家庭情況」獨立】下,獲得這組觀測數據的機率很低很低,基於小几率事件在一次試驗中幾乎不會發生,但它卻發生了,就證實了咱們的「原假設」是不正確的,即有充分證據決絕「原假設」。(這一部分有點繞,其實很簡單,多看幾遍就很是清楚了。)
其實到這裏,咱們對卡方檢驗就已經介紹完了,是否是以爲很簡單。可是在實際操做的過程當中,咱們還會引入 \(p\) 值,不少統計軟件也會幫咱們計算出 \(p\) 值,這個 \(p\) 值是個什麼鬼呢?下面先給出個人結論:
\(p\) 值統一了假設檢驗的比較標準,把計算統計量的機率大小統一變成計算 \(p\) 值,若是這個 \(p\) 值小於一個預先設定好的數,咱們稱之爲「顯著性水平」,用 \(\alpha\) 表示,通常取 \(\alpha = 0.05\),則拒絕原假設,若是 \(p\) 值大於「顯著性水平」,則說明沒有充分證據拒絕原假設。使用 \(p\) 值進行假設檢驗的時候,會更便利。所以,使用 \(p\) 值進行假設檢驗的評判標準就只要一個,就是記住這句話「小拒大接」,即比 \(0.05\) 小,就拒絕「原假設」,比 \(0.05\) 大,結論是「沒有理由拒絕原假設」。
特別說明:這個結論是我根據對 \(p\) 值的理解本身總結的,是人話,但不必定準確。
\(p\) 值在不一樣的檢驗問題中,計算方法會不一樣,在這裏,咱們就以卡方檢驗爲例,若是咱們計算出來的統計量的值爲 \(1\),那麼看圖:
這個時候,統計量取 \(1\) 的機率就很高了,從圖中能夠看出大於 \(0.2\)。咱們做以下分析:
(說明:累計積分和分位點的概念都是十分重要的,在這裏就不贅述了,讀者能夠查閱相關統計學的教材。)
因而,對於卡方檢驗而言,獲得的統計量,咱們能夠計算這個從統計量到正無窮的積分,若是這個積分值小於「顯著性水平」,即認爲這個統計量的機率必定在「顯著性水平」所肯定的臨界點的右邊,即它是比「小几率事件」發生的機率還小的「小几率事件」。
下面,咱們本身寫一個函數來實現卡方檢驗相關的計算,實現和 scipy
軟件包提供的卡方檢驗一樣的效果。
from scipy import stats from scipy.stats import chi2_contingency def custom_chi2_contingency(observed): """ 本身編寫的卡方檢驗的函數,返回 """ # 每一行求和 row = observed.sum(axis=1) # 每一列求和 col = observed.sum(axis=0) # 總數求和 all_sum = observed.sum() # meshgrid 生成網格 x1, x2 = np.meshgrid(col, row) # 指望頻數 expected_count = x1 * x2 / all_sum # 統計量,即卡方值 chi2 = ((observed - expected_count)**2 / expected_count).sum() # 自由度 df = (len(row) - 1) * (len(col) - 1) # 計算 p 值,這裏用到了卡方分佈的機率積累函數, # 由於這個 cdf 是計算從左邊到這點的累計積分,所以用 1 減它 p = 1 - stats.chi2.cdf(chi2, df=df) return chi2, p, df, expected_count
下面驗證自定義函數的正確性:
obs = np.array([[178, 272], [38, 502]]) result1 = custom_chi2_contingency(obs) result2 = chi2_contingency(obs) print('自定義卡方檢驗的函數返回:') print(result1) print() print('scipy 提供的卡方檢驗返回:') print(result2)
顯示:
自定義卡方檢驗的函數返回: (152.16271892047084, 0.0, 1, array([[ 98.18181818, 351.81818182], [117.81818182, 422.18181818]])) scipy 提供的卡方檢驗返回: (150.2623232486362, 1.5192261812214016e-34, 1, array([[ 98.18181818, 351.81818182], [117.81818182, 422.18181818]]))