哈嘍,我是小白~
統(tǒng)計(jì)檢驗(yàn)方法能夠幫助驗(yàn)證模型的性能差異是否具備統(tǒng)計(jì)顯著性,避免結(jié)果偶然。通過這些方法,可以確保實(shí)驗(yàn)結(jié)果具有可重復(fù)性和穩(wěn)健性,從而支持科學(xué)結(jié)論的有效性。此外,統(tǒng)計(jì)檢驗(yàn)還可以幫助發(fā)現(xiàn)不同模型、特征或算法改進(jìn)的真實(shí)影響,避免誤導(dǎo)性優(yōu)化。
今天分享的內(nèi)容,涉及到:
- 卡方檢驗(yàn)(Chi-Square Test)
- Kolmogorov-Smirnov 檢驗(yàn)(K-S 檢驗(yàn))
一起來看下細(xì)節(jié)~
1. t 檢驗(yàn)(t-test)
t 檢驗(yàn)是用于比較兩個樣本均值的假設(shè)檢驗(yàn)方法,假設(shè)數(shù)據(jù)服從正態(tài)分布。它包括單樣本 t 檢驗(yàn)、獨(dú)立樣本 t 檢驗(yàn)和配對樣本 t 檢驗(yàn)。
原理
t 檢驗(yàn)基于樣本均值與總體均值的差異,考慮了樣本標(biāo)準(zhǔn)誤的影響。其關(guān)鍵思想是,如果兩個樣本均值的差異在合理范圍內(nèi),則認(rèn)為它們來自相同的總體,否則就認(rèn)為它們有顯著差異。
核心公式
獨(dú)立樣本 t 檢驗(yàn)的統(tǒng)計(jì)量為:
公式推導(dǎo)
假設(shè)兩個獨(dú)立樣本來自相同的總體。根據(jù)中心極限定理,樣本均值近似服從正態(tài)分布。假設(shè)樣本方差未知,我們使用樣本方差代替總體方差進(jìn)行估計(jì)。
1. 均值的差異:樣本均值的差異為 。
2. 標(biāo)準(zhǔn)誤的計(jì)算:對于兩個樣本均值的標(biāo)準(zhǔn)誤,公式為
3. t 值計(jì)算:將均值差異除以標(biāo)準(zhǔn)誤,得到 t 值:
4. t 分布:通過計(jì)算得到的 t 值,可以根據(jù) t 分布表來確定 p 值,p 值反映了均值差異的顯著性。
5. 自由度:t 分布的自由度為 。
如果計(jì)算出的 t 值超過臨界值,則拒絕零假設(shè),即認(rèn)為兩個樣本的均值顯著不同。
Python實(shí)現(xiàn)
假設(shè)我們想檢驗(yàn)一種新的教學(xué)方法是否比傳統(tǒng)方法更有效。在這個實(shí)驗(yàn)中,我們有兩個獨(dú)立的學(xué)生組:一個組使用傳統(tǒng)教學(xué)方法,另一個組使用新的教學(xué)方法。我們想比較這兩組學(xué)生在最終考試中的平均成績,以確定新的教學(xué)方法是否有顯著提高學(xué)生的成績。
數(shù)據(jù)集描述:
- 傳統(tǒng)方法組:學(xué)生使用傳統(tǒng)教學(xué)方法,他們的成績從某個正態(tài)分布中隨機(jī)生成。
- 新方法組:學(xué)生使用新的教學(xué)方法,他們的成績從另一個正態(tài)分布中隨機(jī)生成。
我們將使用兩個樣本的獨(dú)立 t 檢驗(yàn)來比較這兩個組的平均成績,假設(shè)新方法能提高學(xué)生的平均分?jǐn)?shù)。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
# 設(shè)置隨機(jī)種子,保證結(jié)果的可重復(fù)性
np.random.seed(42)
# 生成虛擬數(shù)據(jù)
# 傳統(tǒng)方法組,正態(tài)分布,均值為70,標(biāo)準(zhǔn)差為10,樣本量為50
traditional_scores = np.random.normal(loc=70, scale=10, size=50)
# 新方法組,正態(tài)分布,均值為75,標(biāo)準(zhǔn)差為12,樣本量為50
new_method_scores = np.random.normal(loc=75, scale=12, size=50)
# 獨(dú)立樣本t檢驗(yàn)
t_stat, p_value = stats.ttest_ind(traditional_scores, new_method_scores)
# 打印t檢驗(yàn)結(jié)果
print(f'T-statistic: {t_stat:.3f}, P-value: {p_value:.3f}')
# 創(chuàng)建一個圖形,包含多個子圖
plt.figure(figsize=(12, 8))
# 1. 箱線圖 (Boxplot)
plt.subplot(2, 2, 1)
sns.boxplot(data=[traditional_scores, new_method_scores], palette='Set2')
plt.xticks([0, 1], ['Traditional Method', 'New Method'])
plt.title('Boxplot of Scores')
# 2. 直方圖 (Histogram)
plt.subplot(2, 2, 2)
sns.histplot(traditional_scores, color='blue', label='Traditional', kde=True, bins=10, stat='density', alpha=0.6)
sns.histplot(new_method_scores, color='red', label='New Method', kde=True, bins=10, stat='density', alpha=0.6)
plt.legend()
plt.title('Histogram of Scores')
plt.xlabel('Score')
plt.ylabel('Density')
# 3. 均值柱狀圖 (Barplot of Means with Standard Error)
means = [np.mean(traditional_scores), np.mean(new_method_scores)]
errors = [stats.sem(traditional_scores), stats.sem(new_method_scores)] # 標(biāo)準(zhǔn)誤
plt.subplot(2, 1, 2)
plt.bar([0, 1], means, yerr=errors, capsize=10, color=['blue', 'red'], alpha=0.7)
plt.xticks([0, 1], ['Traditional Method', 'New Method'])
plt.title('Mean Scores with Standard Error')
plt.ylabel('Mean Score')
# 調(diào)整布局,防止圖像重疊
plt.tight_layout()
# 展示圖形
plt.show()
數(shù)據(jù)生成:我們生成了兩組虛擬數(shù)據(jù),分別代表傳統(tǒng)方法組和新方法組的考試成績。
t 檢驗(yàn):通過 scipy.stats.ttest_ind
進(jìn)行獨(dú)立樣本的 t 檢驗(yàn),檢驗(yàn)兩組平均值是否有顯著差異。
- 箱線圖:展示兩組的成績分布,便于觀察中位數(shù)、四分位距和離群點(diǎn)。可以清晰地展示數(shù)據(jù)的集中趨勢和離散趨勢,幫助判斷數(shù)據(jù)的分布和潛在的異常值。
- 直方圖:展示兩組成績的頻率分布,并疊加核密度估計(jì)曲線,幫助觀察數(shù)據(jù)的形態(tài)及正態(tài)性。結(jié)合核密度估計(jì)曲線,能夠顯示數(shù)據(jù)的分布形狀,便于驗(yàn)證假設(shè)數(shù)據(jù)的正態(tài)性,這對于 t 檢驗(yàn)非常重要。
- 均值柱狀圖:展示每組的平均分和標(biāo)準(zhǔn)誤,直觀地比較均值的差異。結(jié)合標(biāo)準(zhǔn)誤誤差條,能直觀地展示兩組均值的差異及其不確定性,從而幫助評估組間差異的大小。
2. 卡方檢驗(yàn)(Chi-Square Test)
卡方檢驗(yàn)用于判斷兩個分類變量之間是否存在統(tǒng)計(jì)顯著的關(guān)系。常用于頻數(shù)數(shù)據(jù)或分類數(shù)據(jù)的獨(dú)立性檢驗(yàn)和擬合優(yōu)度檢驗(yàn)。
原理
卡方檢驗(yàn)通過比較觀測值與期望值,衡量分類變量的獨(dú)立性。如果實(shí)際觀測值與期望值的差異很大,則認(rèn)為變量之間存在關(guān)聯(lián)。
核心公式
卡方統(tǒng)計(jì)量的計(jì)算公式為:
公式推導(dǎo)
1. 零假設(shè):假設(shè)分類變量是獨(dú)立的。
2. 期望頻數(shù)的計(jì)算:期望頻數(shù) 的計(jì)算為:
3. 差異計(jì)算:計(jì)算每個單元格的觀測頻數(shù) 和期望頻數(shù) 的差異平方。
4. 歸一化差異:用期望頻數(shù) 歸一化差異,計(jì)算卡方統(tǒng)計(jì)量。
5. 卡方分布:最終的卡方統(tǒng)計(jì)量服從卡方分布,其自由度為 ,其中 是行數(shù), 是列數(shù)。
通過查卡方分布表,若卡方統(tǒng)計(jì)量超出臨界值,則拒絕零假設(shè),認(rèn)為兩個變量不獨(dú)立。
Python實(shí)現(xiàn)
有一組虛擬數(shù)據(jù)集,包含兩個分類變量:產(chǎn)品類型(A, B, C)和客戶滿意度(高, 中, 低)。我們想檢驗(yàn)產(chǎn)品類型與客戶滿意度是否存在顯著的關(guān)聯(lián)。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import chi2_contingency
from statsmodels.graphics.mosaicplot import mosaic
# 生成虛擬數(shù)據(jù)
np.random.seed(42)
data = pd.DataFrame({
'Product_Type': np.random.choice(['A', 'B', 'C'], size=300, p=[0.3, 0.4, 0.3]),
'Customer_Satisfaction': np.random.choice(['High', 'Medium', 'Low'], size=300, p=[0.4, 0.3, 0.3])
})
# 生成交叉表
contingency_table = pd.crosstab(data['Product_Type'], data['Customer_Satisfaction'])
# 卡方檢驗(yàn)
chi2, p, dof, expected = chi2_contingency(contingency_table)
# 輸出結(jié)果
print(f'Chi-Square Test Statistic: {chi2}')
print(f'P-value: {p}')
print(f'Degrees of Freedom: {dof}')
print(f'Expected Frequencies: \n{expected}')
# 創(chuàng)建圖像
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 1. 分組柱狀圖
contingency_table.plot(kind='bar', stacked=False, ax=axes[0, 0], color=['#FF6F61', '#6B5B95', '#88B04B'])
axes[0, 0].set_title('Grouped Bar Plot')
axes[0, 0].set_ylabel('Count')
axes[0, 0].set_xlabel('Product Type')
# 2. 熱力圖顯示觀察值和期望值的差異
sns.heatmap(contingency_table - expected, annot=True, cmap='coolwarm', ax=axes[0, 1])
axes[0, 1].set_title('Heatmap of Observed vs Expected')
# 3. 馬賽克圖
mosaic(data, ['Product_Type', 'Customer_Satisfaction'], ax=axes[1, 0], title='Mosaic Plot')
# 4. 堆積柱狀圖
contingency_table.plot(kind='bar', stacked=True, ax=axes[1, 1], color=['#FFA07A', '#20B2AA', '#9370DB'])
axes[1, 1].set_title('Stacked Bar Plot')
axes[1, 1].set_ylabel('Count')
axes[1, 1].set_xlabel('Product Type')
# 調(diào)整布局
plt.tight_layout()
plt.show()
分組柱狀圖:該圖展示了每種產(chǎn)品類型下客戶滿意度的分布,幫助我們直觀比較不同分類的觀測頻次。
熱力圖:展示了觀察值與期望值之間的差異,顏色鮮明的熱力圖可以直觀地顯示是否有顯著偏差。
馬賽克圖:展示了類別之間的相對比例,圖形的面積代表不同類別組合的比例,是一個直觀的方式來展示兩個分類變量之間的關(guān)系。
堆積柱狀圖:展示了不同類別之間的累積分布,便于查看各類別組合的總計(jì)情況。
這些數(shù)據(jù)分析圖形綜合展示了分類變量的頻數(shù)分布、期望與實(shí)際值的差異,以及兩者的關(guān)聯(lián)性。
3. 方差分析(ANOVA)
方差分析用于比較三個或更多樣本的均值差異,常用于多組數(shù)據(jù)的比較。單因素 ANOVA 用于單一因子對響應(yīng)變量的影響分析。
原理
ANOVA 通過比較組間方差和組內(nèi)方差,判斷組間的均值差異是否顯著。組間方差大,說明不同組之間差異顯著;組內(nèi)方差反映了組內(nèi)個體之間的波動。
核心公式
單因素方差分析的 F 值為:
公式推導(dǎo)
1. 零假設(shè):假設(shè)所有組的均值相等,即 。
2. 組間平方和(SSB):計(jì)算各組均值和總體均值的偏差平方:
3. 組內(nèi)平方和(SSW):計(jì)算組內(nèi)數(shù)據(jù)和各組均值的偏差平方:
4. 均方計(jì)算:組間均方(MSB)和組內(nèi)均方(MSW)分別為組間平方和和組內(nèi)平方和除以自由度:
5. F 值計(jì)算:F 統(tǒng)計(jì)量為組間均方與組內(nèi)均方的比值:
6. F 分布:F 統(tǒng)計(jì)量服從 分布,通過查表判斷是否拒絕零假設(shè)。
Python實(shí)現(xiàn)
使用 ANOVA 來檢驗(yàn)不同教學(xué)方法的平均成績是否存在顯著差異。為此,我們將生成虛擬數(shù)據(jù),并通過可視化展示數(shù)據(jù)和結(jié)果。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats as stats
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
import statsmodels.api as sm
# 設(shè)置隨機(jī)種子,生成可重復(fù)的虛擬數(shù)據(jù)
np.random.seed(42)
# 創(chuàng)建虛擬數(shù)據(jù)集:三個教學(xué)方法,每個方法下有 30 名學(xué)生的成績
n_students = 30
method_A = np.random.normal(loc=75, scale=10, size=n_students) # 方法 A 的成績
method_B = np.random.normal(loc=80, scale=12, size=n_students) # 方法 B 的成績
method_C = np.random.normal(loc=70, scale=9, size=n_students) # 方法 C 的成績
# 構(gòu)造數(shù)據(jù)集
df = pd.DataFrame({
'Score': np.concatenate([method_A, method_B, method_C]),
'Method': ['A']*n_students + ['B']*n_students + ['C']*n_students
})
# 1. 方差分析(ANOVA)模型
model = ols('Score ~ Method', data=df).fit()
anova_results = anova_lm(model)
# 2. 提取殘差和擬合值
df['Residuals'] = model.resid
df['Fitted'] = model.fittedvalues
# 設(shè)置繪圖風(fēng)格
sns.set(style='whitegrid', palette='Set2')
# 創(chuàng)建畫布和子圖 (3 行 1 列)
fig, axes = plt.subplots(3, 1, figsize=(10, 15))
# 3. 繪制箱線圖(Boxplot):不同教學(xué)方法的成績分布
sns.boxplot(x='Method', y='Score', data=df, ax=axes[0], linewidth=2.5, width=0.5)
axes[0].set_title('Boxplot of Scores by Teaching Method', fontsize=14)
axes[0].set_xlabel('Teaching Method', fontsize=12)
axes[0].set_ylabel('Scores', fontsize=12)
# 4. 繪制均值和標(biāo)準(zhǔn)誤差圖
mean_se_df = df.groupby('Method').agg(Mean=('Score', 'mean'), SE=('Score', 'sem')).reset_index()
axes[1].errorbar(x=mean_se_df['Method'], y=mean_se_df['Mean'],
yerr=mean_se_df['SE'], fmt='o', ecolor='red', capsize=5, markersize=8, color='blue')
axes[1].set_title('Mean and Standard Error of Scores by Teaching Method', fontsize=14)
axes[1].set_xlabel('Teaching Method', fontsize=12)
axes[1].set_ylabel('Mean Scores', fontsize=12)
# 5. 繪制殘差圖:殘差 vs 擬合值
sns.residplot(x='Fitted', y='Residuals', data=df, ax=axes[2], lowess=True,
scatter_kws={'color': 'purple'}, line_kws={'color': 'orange', 'lw': 2})
axes[2].set_title('Residual Plot', fontsize=14)
axes[2].set_xlabel('Fitted Values', fontsize=12)
axes[2].set_ylabel('Residuals', fontsize=12)
# 調(diào)整圖形布局
plt.tight_layout()
plt.show()
# 輸出方差分析結(jié)果
print('ANOVA Results:\n', anova_results)
虛擬數(shù)據(jù)生成:創(chuàng)建了三個不同教學(xué)方法的學(xué)生成績數(shù)據(jù)集,假設(shè)方法 A、B 和 C 的成績分別服從正態(tài)分布,均值和標(biāo)準(zhǔn)差不同。
ANOVA 檢驗(yàn):通過 statsmodels
庫中的 ols
函數(shù)擬合線性模型,使用 anova_lm
進(jìn)行方差分析。
- 箱線圖:通過箱線圖,我們可以看到每個教學(xué)方法的成績分布情況,便于判斷是否有極端值以及分布的對稱性。
- 均值和標(biāo)準(zhǔn)誤圖:展示了每組的平均成績及其誤差范圍,幫助我們觀察不同教學(xué)方法的平均成績是否存在顯著差異。
- 殘差圖:通過殘差圖,我們可以檢查方差分析模型的殘差是否均勻分布,從而判斷模型擬合的合理性。如果殘差不隨擬合值的增大而增大,模型擬合是合理的。
4. Mann-Whitney U 檢驗(yàn)
Mann-Whitney U 檢驗(yàn)是一種非參數(shù)檢驗(yàn),用于比較兩個獨(dú)立樣本的中位數(shù)差異。它不要求數(shù)據(jù)服從正態(tài)分布,是 t 檢驗(yàn)的非參數(shù)替代方法。
原理
該方法基于樣本秩的比較,如果兩個樣本來自同一總體,兩個樣本的秩序統(tǒng)計(jì)量應(yīng)該混合分布。如果存在中位數(shù)差異,則高秩數(shù)據(jù)偏向某個樣本。
核心公式
Mann-Whitney U 檢驗(yàn)的 U 值公式為:
公式推導(dǎo)
1. 秩賦值:將兩個樣本數(shù)據(jù)合并,按大小為它們賦予秩(小值秩?。?。
2. 秩和計(jì)算:計(jì)算樣本 1 和樣本 2 的秩和 。
3. U 值計(jì)算:
Python實(shí)現(xiàn)
兩個不同的療法(治療A和治療B),用于治療患者的慢性疼痛。每個療法的樣本量為50人,并測量了在療法應(yīng)用后每個患者的疼痛評分。因?yàn)閿?shù)據(jù)不是正態(tài)分布的,所以我們選擇了非參數(shù)檢驗(yàn)中的Mann-Whitney U檢驗(yàn)來比較這兩種療法的療效是否有顯著差異。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import mannwhitneyu
# 設(shè)置隨機(jī)種子,便于復(fù)現(xiàn)
np.random.seed(42)
# 生成兩個虛擬的疼痛評分?jǐn)?shù)據(jù)集 (非正態(tài)分布)
# 療法A的疼痛評分
treatment_A = np.random.beta(a=2, b=5, size=50) * 10 # Beta分布, 放大到0-10范圍
# 療法B的疼痛評分
treatment_B = np.random.beta(a=2.5, b=4, size=50) * 10
# 創(chuàng)建數(shù)據(jù)框
data = pd.DataFrame({
'Pain Score': np.concatenate([treatment_A, treatment_B]),
'Treatment': ['A'] * 50 + ['B'] * 50
})
# Mann-Whitney U檢驗(yàn)
stat, p_value = mannwhitneyu(treatment_A, treatment_B)
print(f'Mann-Whitney U檢驗(yàn)的統(tǒng)計(jì)量: {stat}, p值: {p_value}')
# 畫圖
plt.figure(figsize=(14, 10))
# 子圖1:箱線圖
plt.subplot(2, 2, 1)
sns.boxplot(x='Treatment', y='Pain Score', data=data, palette='Set2')
plt.title('Boxplot of Pain Scores for Two Treatments', fontsize=14)
plt.xlabel('Treatment', fontsize=12)
plt.ylabel('Pain Score', fontsize=12)
# 子圖2:小提琴圖
plt.subplot(2, 2, 2)
sns.violinplot(x='Treatment', y='Pain Score', data=data, palette='Set1')
plt.title('Violin Plot of Pain Scores for Two Treatments', fontsize=14)
plt.xlabel('Treatment', fontsize=12)
plt.ylabel('Pain Score', fontsize=12)
# 子圖3:累積分布函數(shù)(CDF)
plt.subplot(2, 1, 2)
sns.ecdfplot(treatment_A, label='Treatment A', color='blue', lw=2)
sns.ecdfplot(treatment_B, label='Treatment B', color='orange', lw=2)
plt.title('Cumulative Distribution Function (CDF)', fontsize=14)
plt.xlabel('Pain Score', fontsize=12)
plt.ylabel('CDF', fontsize=12)
plt.legend(title='Treatment')
# 調(diào)整布局并展示圖形
plt.tight_layout()
plt.show()
箱線圖:通過中位數(shù)和四分位數(shù)來展示數(shù)據(jù)集的集中趨勢和離散程度,幫助快速發(fā)現(xiàn)兩個療法的中心趨勢是否存在差異。
小提琴圖:相比箱線圖,小提琴圖增加了數(shù)據(jù)分布的密度信息,能展示出數(shù)據(jù)的分布形狀和波動情況,幫助發(fā)現(xiàn)每組數(shù)據(jù)的對稱性和集中情況。
累積分布函數(shù)圖(CDF):展示了每個治療組在特定疼痛評分下的累積概率,可以幫助我們查看兩組數(shù)據(jù)在每個評分區(qū)間的累積分布差異。
這些數(shù)據(jù)分析圖形能夠從多個角度驗(yàn)證治療A和治療B的疼痛評分是否存在顯著差異,結(jié)合Mann-Whitney U檢驗(yàn)的結(jié)果,得出統(tǒng)計(jì)結(jié)論。
5. Kolmogorov-Smirnov 檢驗(yàn)(K-S 檢驗(yàn))
Kolmogorov-Smirnov 檢驗(yàn)用于比較兩個分布的差異,或檢驗(yàn)樣本是否來自某個已知分布。K-S 檢驗(yàn)常用于正態(tài)性檢驗(yàn)。
原理
K-S 檢驗(yàn)基于兩個累積分布函數(shù)(CDF)之間的最大差異。通過比較樣本分布的累積分布函數(shù)和理論分布的累積分布函數(shù),計(jì)算最大差異值 。
核心公式
K-S 檢驗(yàn)統(tǒng)計(jì)量為:
公式推導(dǎo)
1. 累積分布函數(shù)計(jì)算:對于每個樣本,計(jì)算樣本的經(jīng)驗(yàn)累積分布函數(shù)(ECDF)。
2. 最大差異計(jì)算:在每個數(shù)據(jù)點(diǎn)上,計(jì)算兩個累積分布函數(shù)之間的絕對差值,并找到其最大值 。
3. 查表:通過查 Kolmogorov 分布表,判斷 值是否顯著。
Python實(shí)現(xiàn)
生成兩個虛擬數(shù)據(jù)集,一個是正態(tài)分布,另一個是指數(shù)分布,目的是使用 K-S 檢驗(yàn)來判斷它們的分布是否顯著不同。
- 數(shù)據(jù)集 1: 正態(tài)分布 (均值為 0, 標(biāo)準(zhǔn)差為 1)
- 數(shù)據(jù)集 2: 指數(shù)分布 (λ = 1)
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kstest, norm, expon
# 生成虛擬數(shù)據(jù)
np.random.seed(42)
sample_size = 1000
# 數(shù)據(jù)集1:正態(tài)分布
data_norm = np.random.normal(loc=0, scale=1, size=sample_size)
# 數(shù)據(jù)集2:指數(shù)分布
data_expon = np.random.exponential(scale=1, size=sample_size)
# 執(zhí)行K-S檢驗(yàn)
ks_stat, p_value = kstest(data_norm, 'expon', args=(0, 1))
# 生成x軸
x = np.linspace(-2, 8, 1000)
# 獲取累積分布函數(shù) (CDF)
cdf_norm = norm.cdf(x, loc=0, scale=1)
cdf_expon = expon.cdf(x, scale=1)
# 獲取概率密度函數(shù) (PDF)
pdf_norm = norm.pdf(x, loc=0, scale=1)
pdf_expon = expon.pdf(x, scale=1)
# 繪制圖形
fig, ax = plt.subplots(2, 2, figsize=(12, 10))
# 圖1:累積分布函數(shù) (CDF)
ax[0, 0].plot(x, cdf_norm, color='blue', label='Normal CDF', linewidth=2)
ax[0, 0].plot(x, cdf_expon, color='red', label='Exponential CDF', linewidth=2)
ax[0, 0].set_title('Cumulative Distribution Function (CDF)', fontsize=14)
ax[0, 0].legend()
ax[0, 0].grid(True)
# 圖2:概率密度函數(shù) (PDF)
ax[0, 1].plot(x, pdf_norm, color='green', label='Normal PDF', linewidth=2)
ax[0, 1].plot(x, pdf_expon, color='orange', label='Exponential PDF', linewidth=2)
ax[0, 1].set_title('Probability Density Function (PDF)', fontsize=14)
ax[0, 1].legend()
ax[0, 1].grid(True)
# 圖3:經(jīng)驗(yàn)累積分布 (Empirical CDF)
ecdf_norm_x, ecdf_norm_y = np.sort(data_norm), np.arange(1, sample_size+1) / sample_size
ecdf_expon_x, ecdf_expon_y = np.sort(data_expon), np.arange(1, sample_size+1) / sample_size
ax[1, 0].step(ecdf_norm_x, ecdf_norm_y, color='blue', label='Empirical CDF (Normal)', where='post')
ax[1, 0].step(ecdf_expon_x, ecdf_expon_y, color='red', label='Empirical CDF (Exponential)', where='post')
ax[1, 0].set_title('Empirical Cumulative Distribution Function', fontsize=14)
ax[1, 0].legend()
ax[1, 0].grid(True)
# 圖4:K-S統(tǒng)計(jì)量差異點(diǎn)
# 找到差異最大的點(diǎn)(即K-S統(tǒng)計(jì)量對應(yīng)的地方)
ks_diff_point = np.argmax(np.abs(cdf_norm - cdf_expon))
ax[1, 1].plot(x, np.abs(cdf_norm - cdf_expon), color='purple', label='K-S Statistic Difference', linewidth=2)
ax[1, 1].scatter(x[ks_diff_point], np.abs(cdf_norm[ks_diff_point] - cdf_expon[ks_diff_point]),
color='black', zorder=5, label=f'Max Difference: {np.abs(cdf_norm[ks_diff_point] - cdf_expon[ks_diff_point]):.4f}', s=100)
ax[1, 1].set_title('K-S Statistic Difference Plot', fontsize=14)
ax[1, 1].legend()
ax[1, 1].grid(True)
# 顯示結(jié)果
plt.tight_layout()
plt.show()
# 打印K-S檢驗(yàn)結(jié)果
print(f'K-S Statistic: {ks_stat:.4f}, P-value: {p_value:.4f}')
虛擬數(shù)據(jù)生成:data_norm
是從正態(tài)分布生成的數(shù)據(jù)集,均值為 0,標(biāo)準(zhǔn)差為 1。data_expon
是從指數(shù)分布生成的數(shù)據(jù)集,參數(shù) λ=1。
- 圖1:累積分布函數(shù) (CDF) 顯示兩個分布的累積分布曲線,便于直觀比較兩個分布的差異。
- 圖2:概率密度函數(shù) (PDF) 顯示數(shù)據(jù)的概率分布,查看其不同取值范圍內(nèi)的頻率分布情況。
- 圖3:經(jīng)驗(yàn)累積分布 (Empirical CDF) 是基于實(shí)際樣本計(jì)算的經(jīng)驗(yàn)累積分布,展示數(shù)據(jù)的實(shí)際分布情況。
- 圖4:K-S 統(tǒng)計(jì)量差異點(diǎn)圖,展示了累積分布函數(shù)的差異,并標(biāo)出了差異最大的點(diǎn),該點(diǎn)對應(yīng) K-S 檢驗(yàn)中的統(tǒng)計(jì)量。
6. Wilcoxon 符號秩檢驗(yàn)
Wilcoxon 符號秩檢驗(yàn)是一種非參數(shù)檢驗(yàn),用于比較兩個相關(guān)樣本的中位數(shù)差異。通常用于配對樣本的比較。
原理
該檢驗(yàn)根據(jù)兩個樣本之間的差異值,對差異值進(jìn)行排序并賦予秩值,判斷正負(fù)差異是否顯著不同。
核心公式
Wilcoxon 符號秩檢驗(yàn)的統(tǒng)計(jì)量 為:
公式推導(dǎo)
1. 差異計(jì)算:對于配對樣本,計(jì)算每對樣本的差異值 。
2. 秩賦值:將差異值按絕對值排序,賦予秩值。
3. 符號賦值:根據(jù)差異的符號,將正差異和負(fù)差異分別賦值。
4. 統(tǒng)計(jì)量計(jì)算:計(jì)算正差異的秩和 ,并通過查表判斷顯著性。
Python實(shí)現(xiàn)
假設(shè)我們有一組患者,在服用兩種不同的藥物治療前后,我們記錄了他們的體重變化。我們想使用 Wilcoxon 符號秩檢驗(yàn)來比較兩種藥物對體重的影響是否有顯著差異。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import wilcoxon
# 生成虛擬數(shù)據(jù)集
np.random.seed(42)
n = 30 # 樣本數(shù)量
before_treatment = np.random.normal(75, 10, n) # 治療前體重
after_treatment = before_treatment + np.random.normal(-2, 5, n) # 治療后體重(假設(shè)有體重下降)
# 將數(shù)據(jù)放入DataFrame
df = pd.DataFrame({
'Before Treatment': before_treatment,
'After Treatment': after_treatment
})
# 進(jìn)行Wilcoxon符號秩檢驗(yàn)
stat, p_value = wilcoxon(before_treatment, after_treatment)
print(f'Wilcoxon test statistic: {stat}, p-value: {p_value}')
# 畫出多個圖形在一個圖中
plt.figure(figsize=(14, 8))
# 1. 箱線圖(展示治療前后體重的分布)
plt.subplot(2, 2, 1)
sns.boxplot(data=df, palette='Set2')
plt.title('Boxplot of Before and After Treatment')
plt.ylabel('Weight (kg)')
plt.grid(True)
# 2. 密度圖(展示數(shù)據(jù)的概率密度分布)
plt.subplot(2, 2, 2)
sns.kdeplot(before_treatment, label='Before Treatment', color='blue', shade=True)
sns.kdeplot(after_treatment, label='After Treatment', color='red', shade=True)
plt.title('Density Plot of Before and After Treatment')
plt.xlabel('Weight (kg)')
plt.legend()
plt.grid(True)
# 3. 散點(diǎn)圖(展示治療前后配對樣本的體重變化)
plt.subplot(2, 2, 3)
plt.scatter(np.arange(n), before_treatment, color='blue', label='Before Treatment')
plt.scatter(np.arange(n), after_treatment, color='red', label='After Treatment')
for i in range(n):
plt.plot([i, i], [before_treatment[i], after_treatment[i]], color='gray', linestyle='--')
plt.title('Paired Scatter Plot of Before and After Treatment')
plt.xlabel('Sample Index')
plt.ylabel('Weight (kg)')
plt.legend()
plt.grid(True)
# 4. 體重變化的差值分布圖
plt.subplot(2, 2, 4)
weight_diff = after_treatment - before_treatment
sns.histplot(weight_diff, kde=True, color='purple', bins=10)
plt.title('Distribution of Weight Change (After - Before)')
plt.xlabel('Weight Change (kg)')
plt.grid(True)
# 調(diào)整布局并顯示圖像
plt.tight_layout()
plt.show()
箱線圖:用于比較兩組體重?cái)?shù)據(jù)的中位數(shù)和分布差異。如果箱線圖有顯著差異,可能說明兩組數(shù)據(jù)存在系統(tǒng)性變化。
密度圖:展示治療前后體重的分布形態(tài),可以直觀地看出數(shù)據(jù)的集中趨勢和分布情況。
散點(diǎn)圖:每個點(diǎn)對應(yīng)一個患者的體重變化,配對散點(diǎn)圖連線顯示了每個樣本在治療前后的體重差異,有助于可視化個體變化。
體重變化的差值分布圖:展示體重變化的分布,幫助我們理解總體上是增加還是減少體重。
7. Kruskal-Wallis 檢驗(yàn)
Kruskal-Wallis 檢驗(yàn)是一種非參數(shù)檢驗(yàn)方法,用于比較三個或更多獨(dú)立組的中位數(shù)差異,屬于非參數(shù)方差分析(ANOVA)的擴(kuò)展版本。它不要求數(shù)據(jù)服從正態(tài)分布,也不需要組間方差齊性假設(shè)。
原理
Kruskal-Wallis 檢驗(yàn)通過比較樣本的秩次,將所有樣本的觀測值排序并賦予秩次,然后比較不同組的秩和。如果各組的秩和差異顯著,則認(rèn)為這些組的中位數(shù)存在顯著差異。
核心公式
Kruskal-Wallis 檢驗(yàn)的統(tǒng)計(jì)量 計(jì)算公式為:
公式推導(dǎo)
1. 秩排序:將所有樣本的觀測值 (即第 組的第 個觀測值)按大小排序,并賦予秩次。如果有相同的觀測值,則平均賦秩。
2. 計(jì)算秩和:每組數(shù)據(jù)的秩和 計(jì)算為:
3. 統(tǒng)計(jì)量 計(jì)算:將每組的秩和代入公式,得到統(tǒng)計(jì)量 。
4. 檢驗(yàn)結(jié)果:Kruskal-Wallis 檢驗(yàn)的統(tǒng)計(jì)量 近似服從卡方分布,其自由度為 ,其中 是組數(shù)。通過查卡方分布表,判斷 是否顯著。如果 超過臨界值,則拒絕零假設(shè),認(rèn)為組間存在顯著差異。
Python實(shí)現(xiàn)
咱們使用虛擬數(shù)據(jù)集,通過繪制以下數(shù)據(jù)分析圖來說明問題~
箱線圖 (Boxplot):用于顯示不同組的數(shù)據(jù)分布,突出數(shù)據(jù)的中位數(shù)、四分位數(shù)和離群值。
小提琴圖 (Violin Plot):展示數(shù)據(jù)的概率密度分布和數(shù)據(jù)分布的形狀。
條形圖 (Bar Plot):展示不同組的均值和標(biāo)準(zhǔn)誤差,可以用來簡單展示數(shù)據(jù)差異。
Kruskal-Wallis檢驗(yàn)結(jié)果展示圖:在圖像上標(biāo)出顯著性檢驗(yàn)結(jié)果。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import kruskal
# 設(shè)置隨機(jī)種子以確保結(jié)果可重復(fù)
np.random.seed(42)
# 創(chuàng)建虛擬數(shù)據(jù)集 (3組數(shù)據(jù))
group_1 = np.random.normal(loc=5, scale=1.5, size=100)
group_2 = np.random.normal(loc=7, scale=2.0, size=100)
group_3 = np.random.normal(loc=6, scale=1.2, size=100)
# 將數(shù)據(jù)整合到一個DataFrame中
df = pd.DataFrame({
'Value': np.concatenate([group_1, group_2, group_3]),
'Group': ['Group 1']*100 + ['Group 2']*100 + ['Group 3']*100
})
# 進(jìn)行Kruskal-Wallis檢驗(yàn)
stat, p_value = kruskal(group_1, group_2, group_3)
# 創(chuàng)建圖形
plt.figure(figsize=(15, 10))
# 1. 箱線圖 (Boxplot)
plt.subplot(2, 2, 1)
sns.boxplot(x='Group', y='Value', data=df, palette='Set2')
plt.title('Boxplot of Groups')
plt.ylabel('Value')
plt.grid(True)
# 2. 小提琴圖 (Violin Plot)
plt.subplot(2, 2, 2)
sns.violinplot(x='Group', y='Value', data=df, palette='Set1')
plt.title('Violin Plot of Groups')
plt.ylabel('Value')
plt.grid(True)
# 3. 條形圖 (Bar Plot)
plt.subplot(2, 2, 3)
sns.barplot(x='Group', y='Value', data=df, ci='sd', palette='Set3')
plt.title('Bar Plot with Error Bars (Mean ± SD)')
plt.ylabel('Mean Value')
plt.grid(True)
# 4. Kruskal-Wallis 檢驗(yàn)結(jié)果展示
plt.subplot(2, 2, 4)
sns.boxplot(x='Group', y='Value', data=df, palette='coolwarm')
plt.text(0.5, max(df['Value']) - 1, f'Kruskal-Wallis H-statistic: {stat:.2f}', fontsize=12, ha='center')
plt.text(0.5, max(df['Value']) - 2, f'p-value: {p_value:.4f}', fontsize=12, ha='center')
plt.title('Kruskal-Wallis Test Result')
plt.ylabel('Value')
plt.grid(True)
# 調(diào)整圖形布局
plt.tight_layout()
plt.show()
箱線圖 (Boxplot):箱線圖可以直觀地展示每組數(shù)據(jù)的中位數(shù)、四分位范圍和離群值。用于對比不同組數(shù)據(jù)的離散性及位置差異。
小提琴圖 (Violin Plot):相比箱線圖,小提琴圖增加了數(shù)據(jù)的密度估計(jì),使得可以看到每組數(shù)據(jù)的分布形態(tài),尤其是某些組可能的多峰分布。
條形圖 (Bar Plot):簡單展示各組的均值和標(biāo)準(zhǔn)誤差,能讓人更容易看出數(shù)據(jù)的集中趨勢與變異情況。
Kruskal-Wallis 檢驗(yàn)結(jié)果展示圖:在數(shù)據(jù)分布圖形上標(biāo)注Kruskal-Wallis檢驗(yàn)結(jié)果,說明各組之間是否存在顯著差異。這種展示方式可以將統(tǒng)計(jì)結(jié)果和數(shù)據(jù)分布可視化地結(jié)合在一起。
8. Fisher 精確檢驗(yàn)
Fisher 精確檢驗(yàn)用于處理兩個分類變量之間的獨(dú)立性檢驗(yàn),特別適用于小樣本數(shù)據(jù)或 的列聯(lián)表。它通過計(jì)算每種可能的樣本排列概率,準(zhǔn)確判斷兩個變量是否獨(dú)立。
原理
Fisher 精確檢驗(yàn)基于超幾何分布,計(jì)算在 列聯(lián)表中,實(shí)際觀察到的樣本排列是否與假設(shè)的獨(dú)立性一致。檢驗(yàn)通過所有可能的排列概率之和,得出是否存在顯著性差異。
核心公式
Fisher 精確檢驗(yàn)的公式為:
公式推導(dǎo)
1. 列聯(lián)表定義:給定 的列聯(lián)表:
2. 超幾何分布:假設(shè)行變量和列變量獨(dú)立,則樣本中的各元素服從超幾何分布。列聯(lián)表中的元素表示抽樣結(jié)果,而超幾何分布計(jì)算某個特定組合發(fā)生的概率。
3. 組合數(shù)計(jì)算:Fisher 精確檢驗(yàn)通過計(jì)算所有可能的列聯(lián)表配置,并基于每種配置的概率計(jì)算總體顯著性。
4. p 值計(jì)算:將所有更極端的組合概率相加,得到總的 p 值。如果 p 值小于顯著性水平 ,則拒絕獨(dú)立性假設(shè)。
Python實(shí)現(xiàn)
假設(shè)我們想研究一個醫(yī)院中不同年齡段(青年、中年、老年)患者是否在不同性別(男性、女性)之間的就診頻率有顯著差異。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import fisher_exact
from statsmodels.graphics.mosaicplot import mosaic
from matplotlib import colors
# 設(shè)置隨機(jī)種子
np.random.seed(42)
# 虛擬數(shù)據(jù)集
data = {
'Age Group': np.random.choice(['Youth', 'Middle-aged', 'Senior'], size=100),
'Gender': np.random.choice(['Male', 'Female'], size=100)
}
df = pd.DataFrame(data)
# 選擇兩個年齡組
df_filtered = df[df['Age Group'].isin(['Youth', 'Middle-aged'])]
# 生成交叉表
contingency_table = pd.crosstab(df_filtered['Age Group'], df_filtered['Gender'])
# 進(jìn)行 Fisher 精確檢驗(yàn)
oddsratio, p_value = fisher_exact(contingency_table)
print(f'Fisher Exact Test p-value: {p_value}')
# 繪制分析圖形
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
# 圖1:堆疊條形圖
contingency_table.plot(kind='bar', stacked=True, ax=axes[0], color=['#FF9999','#66B3FF'])
axes[0].set_title('Stacked Bar Plot of Age Group vs Gender')
axes[0].set_xlabel('Age Group')
axes[0].set_ylabel('Count')
axes[0].legend(title='Gender')
# 圖2:熱圖
sns.heatmap(contingency_table, annot=True, fmt='d', cmap='YlGnBu', cbar=True, ax=axes[1])
axes[1].set_title('Heatmap of Age Group vs Gender')
# 圖3:馬賽克圖
props = lambda key: {'color': ['#FF9999','#66B3FF'][key[1] == 'Female']}
mosaic(df_filtered, ['Age Group', 'Gender'], ax=axes[2], properties=props)
axes[2].set_title('Mosaic Plot of Age Group vs Gender')
# 調(diào)整布局
plt.tight_layout()
plt.show()
堆疊條形圖:通過條形的高度和顏色來比較不同性別在各個年齡段的分布,觀察是否存在顯著的比例差異。
熱圖:交叉表的頻數(shù)通過顏色強(qiáng)度展示,便于直觀觀察哪些組合的頻次較高或較低。
馬賽克圖:通過各矩形區(qū)域的大小展示不同年齡組和性別的組合頻率,面積越大,頻率越高,清晰呈現(xiàn)比例關(guān)系。
9. McNemar 檢驗(yàn)
McNemar 檢驗(yàn)用于分析配對樣本的分類變量,特別是比較兩種處理結(jié)果在二分類變量上的差異。它常用于評估兩種診斷方法或?qū)嶒?yàn)前后差異。
原理
McNemar 檢驗(yàn)基于配對樣本的 列聯(lián)表,通過比較兩種結(jié)果的差異,判斷處理前后的變化是否顯著。特別關(guān)注變化的方向和不對稱性。
核心公式
McNemar 檢驗(yàn)的統(tǒng)計(jì)量為:
- 和 是列聯(lián)表中配對樣本的不同響應(yīng)數(shù)
公式推導(dǎo)
1. 列聯(lián)表定義:對于配對樣本數(shù)據(jù),構(gòu)造 列聯(lián)表:
其中 和 表示處理前后響應(yīng)一致的個數(shù), 和 表示響應(yīng)改變的個數(shù)。2. 檢驗(yàn)差異:McNemar 檢驗(yàn)重點(diǎn)分析 和 的不對稱性,表示樣本在兩個處理結(jié)果之間的不同變化。通過檢驗(yàn) 和 的差異是否顯著,判斷處理是否有效。
3. 統(tǒng)計(jì)量計(jì)算:計(jì)算 McNemar 統(tǒng)計(jì)量:
4. 自由度與顯著性:該統(tǒng)計(jì)量服從自由度為 1 的卡方分布。如果 超過臨界值,則認(rèn)為兩個處理結(jié)果有顯著差異。
Python實(shí)現(xiàn)
通過分析一個假設(shè)的二分類變量的變化(例如,測試前后某個治療方法的效果),并展示數(shù)據(jù)的分布、變化情況及其統(tǒng)計(jì)結(jié)果。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.stats.contingency_tables import mcnemar
# 設(shè)置隨機(jī)種子以保證結(jié)果可重現(xiàn)
np.random.seed(42)
# 生成虛擬數(shù)據(jù)
# 前后狀態(tài): 0 = 未好轉(zhuǎn), 1 = 好轉(zhuǎn)
data = {
'Before': [0] * 14 + [1] * 36, # 14人未好轉(zhuǎn),36人好轉(zhuǎn)
'After': [0] * 10 + [1] * 26 + [0] * 14 # 10人好轉(zhuǎn),26人未好轉(zhuǎn)
}
df = pd.DataFrame(data)
# 進(jìn)行 McNemar 檢驗(yàn)
# 形成 2x2 頻數(shù)表
table = pd.crosstab(df['Before'], df['After'])
print('2x2 Contingency Table:')
print(table)
# McNemar 檢驗(yàn)
result = mcnemar(table, exact=False)
print(f'McNemar Test Results: Statistic = {result.statistic}, p-value = {result.pvalue}')
# 可視化
plt.figure(figsize=(14, 8))
# 堆疊條形圖
plt.subplot(2, 2, 1)
sns.countplot(data=df, x='Before', hue='After', palette='bright')
plt.title('Change in Status Before and After Treatment')
plt.xticks([0, 1], ['Not Improved', 'Improved'])
plt.ylabel('Count')
# 混淆矩陣
plt.subplot(2, 2, 2)
sns.heatmap(table, annot=True, fmt='d', cmap='viridis', cbar=False, xticklabels=['Not Improved', 'Improved'], yticklabels=['Not Improved', 'Improved'])
plt.title('Confusion Matrix')
plt.xlabel('Post-Treatment Status')
plt.ylabel('Pre-Treatment Status')
# 比例餅圖
plt.subplot(2, 2, (3, 4))
proportions = table.values.flatten()
labels = ['Not Improved-Not Improved', 'Not Improved-Improved', 'Improved-Not Improved', 'Improved-Improved']
plt.pie(proportions, labels=labels, autopct='%1.1f%%', startangle=90, colors=sns.color_palette('bright', len(labels)))
plt.title('Proportional Change in Status')
plt.tight_layout()
plt.show()
數(shù)據(jù)生成:使用 NumPy 和 Pandas 創(chuàng)建一個包含治療前后狀態(tài)的虛擬數(shù)據(jù)集。“Before”列表示治療前的狀態(tài),“After”列表示治療后的狀態(tài)。
McNemar 檢驗(yàn):使用 statsmodels
庫中的 mcnemar
方法進(jìn)行 McNemar 檢驗(yàn),輸出統(tǒng)計(jì)量和 p 值,以判斷治療效果的顯著性。
- 堆疊條形圖顯示治療前后狀態(tài)的變化情況,便于直觀了解各狀態(tài)的人數(shù)分布。
- 混淆矩陣用熱圖表示,幫助理解實(shí)際狀態(tài)與預(yù)測狀態(tài)之間的關(guān)系。
- 比例餅圖清晰展示狀態(tài)變化的比例,增強(qiáng)結(jié)果的可讀性。
通過 McNemar 檢驗(yàn),我們可以分析治療前后狀態(tài)的變化是否具有統(tǒng)計(jì)學(xué)顯著性。圖形化分析不僅可以直觀呈現(xiàn)數(shù)據(jù)的分布情況,還可以幫助識別數(shù)據(jù)中的趨勢和模式。
10. Cochran's Q 檢驗(yàn)
Cochran's Q 檢驗(yàn)是一種非參數(shù)檢驗(yàn),用于分析多個相關(guān)樣本的二分類變量差異。它是 McNemar 檢驗(yàn)的擴(kuò)展,可以處理三個或更多相關(guān)樣本的情況。
原理
Cochran's Q 檢驗(yàn)基于多個相關(guān)樣本的二分類數(shù)據(jù),通過比較不同處理組的二分類結(jié)果是否一致,判斷不同處理是否存在顯著性差異。
核心公式
Cochran's Q 檢驗(yàn)的統(tǒng)計(jì)量為:
- 是第 組第 個樣本的響應(yīng)(0 或 1)
公式推導(dǎo)
1. 列聯(lián)表構(gòu)造:針對每個樣本的多個處理結(jié)果,構(gòu)造 的二分類矩陣,每個元素 代表樣本 在處理 下的響應(yīng)。
2. 總響應(yīng)數(shù)計(jì)算:對于每個處理組,計(jì)算總響應(yīng)數(shù) 。
3. 統(tǒng)計(jì)量 計(jì)算:通過總響應(yīng)數(shù)和樣本的響應(yīng)差異,計(jì)算 Cochran's Q 統(tǒng)計(jì)量:
4. 顯著性檢驗(yàn):Q 統(tǒng)計(jì)量服從自由度為 的卡方分布,通過查表判斷是否顯著。如果 超過臨界值,則不同處理之間存在顯著性差異。
Python實(shí)現(xiàn)
假設(shè)我們有 10 個患者,他們接受了三種不同的治療(藥物A、藥物B 和藥物C)。對于每個患者,我們記錄了每種治療是否成功(成功用 1
表示,失敗用 0
表示)。我們想知道這三種治療方法的成功率是否有顯著差異。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.stats.contingency_tables import cochrans_q
# 生成虛擬數(shù)據(jù)集
np.random.seed(42)
data = {
'Patient': ['Patient {}'.format(i+1) for i in range(10)],
'Drug A': np.random.randint(0, 2, size=10),
'Drug B': np.random.randint(0, 2, size=10),
'Drug C': np.random.randint(0, 2, size=10)
}
df = pd.DataFrame(data)
df.set_index('Patient', inplace=True)
# Cochran's Q 檢驗(yàn)
# Reshape data for Cochran's Q test
data_for_cochrans_q = df.values.T # Transpose the DataFrame to get treatments as rows
q_stat, p_value = cochrans_q(data_for_cochrans_q)
print(f'Cochran's Q 檢驗(yàn)統(tǒng)計(jì)量: {q_stat:.4f}, p值: {p_value:.4f}')
# 可視化分析
fig, axs = plt.subplots(2, 2, figsize=(12, 12))
# 1. 條形圖:展示每種治療的成功率
success_rate = df.mean().sort_values(ascending=False)
axs[0, 0].bar(success_rate.index, success_rate, color=['blue', 'green', 'red'])
axs[0, 0].set_title('Comparison of Success Rates for Treatments')
axs[0, 0].set_ylabel('Success Rate')
axs[0, 0].set_ylim(0, 1)
# 2. 熱力圖:展示每個患者在不同治療中的結(jié)果
sns.heatmap(df, cmap='coolwarm', linewidths=1, linecolor='black', cbar=False, ax=axs[0, 1])
axs[0, 1].set_title('Heatmap of Patient Treatment Outcomes')
# 3. 點(diǎn)圖:展示患者在每種治療中的成功與失敗情況
for i, drug in enumerate(df.columns):
axs[1, 0].scatter(df.index, df[drug] + i * 0.1, label=drug, s=100, alpha=0.8)
axs[1, 0].set_yticks([0, 1])
axs[1, 0].set_yticklabels(['Failure', 'Success'])
axs[1, 0].legend()
axs[1, 0].set_title('Patient Treatment Outcomes Scatter Plot')
# 4. 箱線圖:展示不同治療結(jié)果的分布
df_melt = df.melt(var_name='Drug', value_name='Outcome')
sns.boxplot(x='Drug', y='Outcome', data=df_melt, palette='Set2', ax=axs[1, 1])
axs[1, 1].set_title('Distribution of Treatment Outcomes')
plt.tight_layout()
plt.show()
條形圖:展示了三種藥物的成功率對比,能夠快速識別哪個藥物成功率較高或較低。條形圖非常適合展示分類變量的頻率或比例,因此我們使用它來比較藥物成功率。
熱力圖:展示每個患者在不同藥物下的成功或失敗情況,顏色的變化使得成功與失敗的模式更直觀。熱力圖可以清晰地呈現(xiàn)每個患者的結(jié)果模式,通過顏色對比,易于觀察每種治療方法的差異。
點(diǎn)圖(Dot Plot):每個患者的每次治療結(jié)果用點(diǎn)表示,多個治療之間有輕微位移,使得結(jié)果的層次更加明顯。點(diǎn)圖可以展示出每個個體在不同治療中的詳細(xì)結(jié)果,能夠從個體層面上評估成功與失敗情況。
箱線圖:展示了不同治療方法的結(jié)果分布。雖然數(shù)據(jù)是二值的,但仍然可以通過箱線圖可視化各組的集中趨勢和離散情況。箱線圖適合展示數(shù)據(jù)的分布和離散情況,盡管我們的數(shù)據(jù)是二進(jìn)制,但仍然可以用于展示治療效果的波動。
通過這些圖形和Cochran's Q檢驗(yàn)結(jié)果,我們可以得出對三種藥物的成功率差異的結(jié)論。如果p值小于顯著性水平(通常是0.05),則說明三種藥物的成功率有顯著差異。