大家好~
今天想要和大家来一起聊聊关于统计检验方法 的内容。
统计检验方法能够验证数据的分布是否符合模型假设,例如通过正态性检验来确保数据适合于线性模型,从而减少模型误判的风险。特征选择与降维方面,通过相关性检验和显著性检验,统计方法帮助识别和选择对模型预测有意义的特征,减少冗余特征,提升模型的泛化能力。
统计检验用于比较不同模型的性能,验证实验结果的显著性,确保所选模型在多个数据集上的优越性不是偶然现象。
今天分享的10种 统计检验方法有:
t检验 卡方检验 方差分析 线性回归分析 非参数检验 假设检验 F检验 相关系数检验 正态性检验 显著性检验
下面,我会把每个方面的理论解释、核心点、数学公式推导等等给大家讲解清楚~
1. t检验
简介
t检验用于比较两个样本均值之间的差异,以判断是否有显著性差异。分为单样本t检验、独立样本t检验和配对样本t检验。
原理
通过假设检验的方式,我们可以判断两个样本均值是否显著不同。t检验基于正态分布,假设数据符合正态性。
核心点:
单样本t检验:测试一个样本均值是否与已知总体均值显著不同。 独立样本t检验:测试两个独立样本的均值差异。 配对样本t检验:用于成对数据(如实验前后测试数据)的均值差异分析。
公式
单样本t检验的统计量公式为:
其中:
为样本均值 为总体均值 为样本标准差 为样本数量
Python代码
我们将生成两个样本数据集,分别代表“治疗组”和“对照组”,并进行独立样本t检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 生成随机数据:两个独立样本
np.random.seed(1)
treatment = np.random.normal(50, 5, 100) # 治疗组
control = np.random.normal(52, 5, 100) # 对照组
# 进行独立样本t检验
t_stat, p_value = stats.ttest_ind(treatment, control)
# 绘图
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 数据分布直方图
sns.histplot(treatment, kde=True, color='blue', label="Treatment", ax=axs[0, 0])
sns.histplot(control, kde=True, color='orange', label="Control", ax=axs[0, 0])
axs[0, 0].legend()
axs[0, 0].set_title("Treatment vs Control Distribution")
# 均值比较条形图
axs[0, 1].bar(["Treatment", "Control"], [np.mean(treatment), np.mean(control)], color=['blue', 'orange'])
axs[0, 1].set_title("Mean Comparison")
# 箱线图
sns.boxplot(data=[treatment, control], ax=axs[1, 0], palette="Set2")
axs[1, 0].set_xticklabels(["Treatment", "Control"])
axs[1, 0].set_title("Boxplot of Treatment vs Control")
# t统计量和p值展示
axs[1, 1].text(0.1, 0.5, f"t-statistic: {t_stat:.3f}\np-value: {p_value:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
2. 卡方检验
简介
卡方检验用于分析两个分类变量之间的关系,主要应用于独立性检验(用于判断两个变量是否独立)和拟合优度检验(用于评估样本数据与理论分布的匹配程度)。
原理
通过比较实际观测频数和期望频数的差异,计算卡方值,并判断该值是否显著。较大的卡方值表明变量之间有较强的关联。
核心点:
独立性检验:用于检测两个分类变量是否相互独立。 拟合优度检验:用于检验一个样本数据的分布是否与预期分布相匹配。
公式
卡方统计量公式:
其中:
:观测频数 :期望频数
Python代码
构造一个模拟数据集,并进行卡方独立性检验。
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据:两个分类变量(性别和偏好)
data = np.array([[20, 15, 10], [30, 40, 15]])
# 卡方独立性检验
chi2, p, dof, expected = stats.chi2_contingency(data)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 实际频数热力图
sns.heatmap(data, annot=True, fmt="d", cmap="Blues", ax=axs[0, 0])
axs[0, 0].set_title("Observed Frequencies")
# 期望频数热力图
sns.heatmap(expected, annot=True, fmt=".1f", cmap="Reds", ax=axs[0, 1])
axs[0, 1].set_title("Expected Frequencies")
# 差值热力图
sns.heatmap(data - expected, annot=True, fmt=".1f", cmap="coolwarm", ax=axs[1, 0])
axs[1, 0].set_title("Observed - Expected Difference")
# 卡方统计量和p值展示
axs[1, 1].text(0.1, 0.5, f"Chi-square: {chi2:.2f}\np-value: {p:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
3. 方差分析
简介
方差分析(ANOVA)用于比较多个组的均值差异。它分析的是组间方差与组内方差的比率,通过F分布来判断差异是否显著。
原理
方差分析基于总方差分解,将其分为组内和组间方差,通过F检验判断组间均值差异是否显著。
核心点:
单因素方差分析:一个因子多组均值差异。 双因素方差分析:两个因子及其交互作用的均值差异。
公式
单因素方差分析的F统计量:
Python代码
使用三个不同组的数据集进行单因素方差分析。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据生成
group1 = np.random.normal(24, 5, 50)
group2 = np.random.normal(28, 5, 50)
group3 = np.random.normal(26, 5, 50)
# 单因素方差分析
f_stat, p_value = stats.f_oneway(group1, group2, group3)
# 绘图
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 数据分布
sns.histplot(group1, kde=True, ax=axs[0, 0], color="skyblue", label="Group1")
sns.histplot(group2, kde=True, ax=axs[0, 0], color="orange", label="Group2")
sns.histplot(group3, kde=True, ax=axs[0, 0], color="green", label="Group3")
axs[0, 0].legend()
axs[0, 0].set_title("Group Distribution")
# 均值条形图
axs[0, 1].bar(["Group1", "Group2", "Group3"], [np.mean(group1), np.mean(group2), np.mean(group3)], color=["skyblue", "orange", "green"])
axs[0, 1].set_title("Mean Comparison")
# 箱线图
sns.boxplot(data=[group1, group2, group3], ax=axs[1, 0], palette="Set2")
axs[1, 0].set_xticklabels(["Group1", "Group2", "Group3"])
axs[1, 0].set_title("Box Plot Comparison")
# F值和p值展示
axs[1, 1].text(0.1, 0.5, f"F-statistic: {f_stat:.2f}\np-value: {p_value:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
4. 线性回归分析
简介
线性回归是一种用于研究两个或多个变量之间关系的统计方法
。通过拟合线性方程预测因变量。
原理
通过最小二乘法拟合自变量和因变量的线性关系,得出自变量对因变量的解释能力。
核心点:
简单线性回归:一个自变量的情况。 多元线性回归:多个自变量的情况。
公式
简单线性回归模型为:
其中 和 为回归系数, 为误差项。
Python代码
使用随机生成数据并通过线性回归分析,预测自变量和因变量之间的关系。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
# 数据生成
X = np.random.rand(100, 1) * 10
y = 2.5 * X + np.random.normal(0, 1, (100, 1))
# 模型训练
model = LinearRegression()
model.fit(X, y)
y_pred = model.predict(X)
# 绘图
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 散点图和拟合线
axs[0, 0].scatter(X, y, color="blue", label="Data")
axs[0, 0].plot(X, y_pred, color="red", label="Fitted Line")
axs[0, 0].legend()
axs[0, 0].set_title("Linear Regression Fit")
# 残差分布
residuals = y - y_pred
sns.histplot(residuals, kde=True, ax=axs[0, 1])
axs[0, 1].set_title("Residual Distribution")
# 预测值 vs 实际值
axs[1, 0].scatter(y, y_pred, color="purple")
axs[1, 0].plot(y, y, color="black", linestyle="--")
axs[1, 0].set_title("Predicted vs Actual")
# 模型系数
axs[1, 1].text(0.1, 0.5, f"Slope: {model.coef_[0][0]:.2f}\nIntercept: {model.intercept_[0]:.2f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
5. 相关性分析
简介
相关性分析用于研究两个变量之间的线性关系。最常用的相关性系数包括皮尔逊相关系数和斯皮尔曼秩相关系数。
原理
相关性度量了两个变量在数值上的线性关联程度。相关系数范围在-1到1之间,值越接近±1,表示相关性越强。
核心点:
皮尔逊相关系数:用于线性关系的度量,假设数据服从正态分布。 斯皮尔曼秩相关系数:用于非线性关系,基于变量的秩次进行相关性分析。
公式
皮尔逊相关系数公式为:
Python代码
我们将生成两个相关数据集并计算皮尔逊和斯皮尔曼相关系数。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据生成
np.random.seed(10)
X = np.random.normal(50, 10, 100)
Y = 2.5 * X + np.random.normal(0, 10, 100)
# 计算相关性
pearson_corr, _ = stats.pearsonr(X, Y)
spearman_corr, _ = stats.spearmanr(X, Y)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 散点图和拟合线
sns.scatterplot(x=X, y=Y, ax=axs[0, 0], color="blue")
sns.regplot(x=X, y=Y, ax=axs[0, 0], color="red", scatter=False)
axs[0, 0].set_title("Scatter Plot with Fitted Line")
# 皮尔逊相关性直方图
sns.histplot(X, color="skyblue", label="X Distribution", ax=axs[0, 1], kde=True)
sns.histplot(Y, color="orange", label="Y Distribution", ax=axs[0, 1], kde=True)
axs[0, 1].legend()
axs[0, 1].set_title("Distributions of X and Y")
# 相关性矩阵热力图
corr_matrix = np.corrcoef(X, Y)
sns.heatmap(corr_matrix, annot=True, fmt=".2f", cmap="coolwarm", ax=axs[1, 0])
axs[1, 0].set_title("Correlation Matrix Heatmap")
# 显示相关系数
axs[1, 1].text(0.1, 0.5, f"Pearson Correlation: {pearson_corr:.2f}\nSpearman Correlation: {spearman_corr:.2f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
6. 正态性检验
简介
正态性检验用于判断数据是否符合正态分布。常用方法包括Shapiro-Wilk检验、Kolmogorov-Smirnov检验和Anderson-Darling检验。
原理
正态性检验基于正态分布的假设,如果数据偏离正态分布较大,则拒绝原假设(数据不符合正态分布)。
核心点:
Shapiro-Wilk检验:用于小样本正态性检验,检验统计量越接近1,表示数据越符合正态分布。 Kolmogorov-Smirnov检验:用于检验数据与正态分布的吻合度。
Python代码
我们生成正态分布数据并进行Shapiro-Wilk和Kolmogorov-Smirnov正态性检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据生成
data = np.random.normal(0, 1, 100)
# 正态性检验
shapiro_stat, shapiro_p = stats.shapiro(data)
ks_stat, ks_p = stats.kstest(data, 'norm')
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 直方图和正态拟合曲线
sns.histplot(data, kde=True, ax=axs[0, 0])
axs[0, 0].set_title("Histogram of Data with KDE")
# QQ图
stats.probplot(data, dist="norm", plot=axs[0, 1])
axs[0, 1].set_title("QQ Plot")
# 显示Shapiro-Wilk和KS检验结果
axs[1, 0].text(0.1, 0.5, f"Shapiro-Wilk p-value: {shapiro_p:.4f}\nKS Test p-value: {ks_p:.4f}", fontsize=14)
axs[1, 0].set_axis_off()
# 正态分布拟合图
sns.kdeplot(data, ax=axs[1, 1])
sns.kdeplot(np.random.normal(np.mean(data), np.std(data), 100), ax=axs[1, 1], linestyle="--", color="red")
axs[1, 1].set_title("Fitted Normal Distribution")
plt.tight_layout()
plt.show()
7. Mann-Whitney U检验
简介
Mann-Whitney U检验是一种非参数检验,用于比较两个独立样本的中位数差异,适用于数据不满足正态分布的情况。
原理
Mann-Whitney U检验通过比较两个样本之间的秩和差异,以判断两组样本是否来自相同分布。
公式
计算U统计量的公式:
其中 为样本1的秩和。
Python代码
生成两个非正态分布数据集并进行Mann-Whitney U检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据生成
group_a = np.random.exponential(scale=2, size=100)
group_b = np.random.exponential(scale=2.5, size=100)
# Mann-Whitney U检验
u_stat, p_value = stats.mannwhitneyu(group_a, group_b)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 数据分布直方图
sns.histplot(group_a, kde=True, ax=axs[0, 0], color="skyblue", label="Group A")
sns.histplot(group_b, kde=True, ax=axs[0, 0], color="orange", label="Group B")
axs[0, 0].legend()
axs[0, 0].set_title("Distribution of Group A and Group B")
# 箱线图
sns.boxplot(data=[group_a, group_b], ax=axs[0, 1], palette="Set2")
axs[0, 1].set_xticklabels(["Group A", "Group B"])
axs[0, 1].set_title("Box Plot of Group A and Group B")
# QQ图
stats.probplot(group_a, dist="norm", plot=axs[1, 0])
axs[1, 0].set_title("QQ Plot of Group A")
# U统计量和p值
axs[1, 1].text(0.1, 0.5, f"Mann-Whitney U: {u_stat:.2f}\np-value: {p_value:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
8. Kruskal-Wallis检验
简介
Kruskal-Wallis检验是一种非参数检验,用于比较多组数据的中位数是否显著不同,适用于数据不满足正态分布或方差齐性的情况。
原理
Kruskal-Wallis检验基于秩和的分布差异来分析多个组的分布是否相同。
核心公式: Kruskal-Wallis检验的H统计量公式:
其中 为第 组的秩和, 为第 组样本大小。
Python代码
生成三个非正态分布的组数据并进行Kruskal-Wallis检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 数据生成
group1 = np.random.exponential(scale=2, size=50)
group2 = np.random.exponential(scale=2.5, size=50)
group3 = np.random.exponential(scale=3, size=50)
# Kruskal-Wallis检验
h_stat, p_value = stats.kruskal(group1, group2, group3)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 数据分布直方图
sns.histplot(group1, kde=True, ax=axs[0, 0], color="skyblue", label="Group 1")
sns.histplot(group2, kde=True, ax=axs[0, 0], color="orange", label="Group 2")
sns.histplot(group3, kde=True, ax=axs[0, 0], color="green", label="Group 3")
axs[0, 0].legend()
axs[0, 0].set_title("Distribution of Group 1, Group 2 and Group 3")
# 箱线图
sns.boxplot(data=[group1, group2, group3], ax=axs[0, 1], palette="Set2")
axs[0, 1].set_xticklabels(["Group 1", "Group 2", "Group 3"])
axs[0, 1].set_title("Box Plot Comparison")
# QQ图
stats.probplot(group1, dist="norm", plot=axs[1, 0])
axs[1, 0].set_title("QQ Plot of Group 1")
# H统计量和p值展示
axs[1, 1].text(0.1, 0.5, f"Kruskal-Wallis H: {h_stat:.2f}\np-value: {p_value:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()
9. 卡方检验
简介
卡方检验用于分析分类变量之间的关联性。常用于独立性检验和拟合优度检验。
原理
卡方检验通过计算实际值和期望值之间的差异来判断变量是否独立。较大的卡方统计量意味着实际观察值与期望值的差异显著,表示变量可能相关。
核心点:
独立性检验:判断两个分类变量是否相关。 拟合优度检验:判断观测值是否符合特定的理论分布。
公式
卡方统计量的公式为:
其中 为观测频数, 为期望频数。
Python代码
使用随机生成的分类数据集,进行卡方独立性检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import chi2_contingency
# 数据生成
data = pd.DataFrame({
"Category_A": np.random.choice(["Yes", "No"], size=100),
"Category_B": np.random.choice(["Male", "Female"], size=100)
})
# 交叉表
contingency_table = pd.crosstab(data["Category_A"], data["Category_B"])
# 卡方检验
chi2, p, dof, expected = chi2_contingency(contingency_table)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 交叉表展示
sns.heatmap(contingency_table, annot=True, fmt="d", cmap="coolwarm", ax=axs[0, 0])
axs[0, 0].set_title("Contingency Table")
# 期望频数热力图
sns.heatmap(expected, annot=True, fmt=".2f", cmap="coolwarm", ax=axs[0, 1])
axs[0, 1].set_title("Expected Frequencies")
# 显示卡方检验结果
axs[1, 0].text(0.1, 0.5, f"Chi-Square: {chi2:.2f}\nDegrees of Freedom: {dof}\np-value: {p:.4f}", fontsize=14)
axs[1, 0].set_axis_off()
# 频数分布柱状图
contingency_table.plot(kind="bar", stacked=True, color=["skyblue", "orange"], ax=axs[1, 1])
axs[1, 1].set_title("Stacked Bar Chart of Categories")
plt.tight_layout()
plt.show()
10. 配对样本的威尔科克森符号秩检验
简介
威尔科克森符号秩检验是非参数检验,用于比较配对样本的中位数差异。适合于数据不满足正态性,或包含离群值的配对样本。
原理
该检验通过比较两组配对数据的秩次和符号,来分析两组数据的差异是否显著。
核心点:
应用场景:配对样本非正态分布情况。 秩次符号:用于衡量配对数据的差异性。
Python代码
生成配对样本数据并进行威尔科克森符号秩检验。
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import wilcoxon
# 数据生成
pre_treatment = np.random.normal(5, 2, 30)
post_treatment = pre_treatment + np.random.normal(0.5, 1, 30)
# 威尔科克森符号秩检验
w_stat, p_value = wilcoxon(pre_treatment, post_treatment)
# 图表绘制
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 配对数据分布散点图
sns.scatterplot(x=pre_treatment, y=post_treatment, ax=axs[0, 0], color="purple")
axs[0, 0].plot([pre_treatment.min(), pre_treatment.max()], [pre_treatment.min(), pre_treatment.max()], color="black", linestyle="--")
axs[0, 0].set_title("Scatter Plot of Pre vs. Post Treatment")
# 配对数据差值直方图
diff = post_treatment - pre_treatment
sns.histplot(diff, kde=True, ax=axs[0, 1], color="green")
axs[0, 1].set_title("Histogram of Paired Differences")
# 箱线图
sns.boxplot(data=[pre_treatment, post_treatment], ax=axs[1, 0], palette="Set2")
axs[1, 0].set_xticklabels(["Pre Treatment", "Post Treatment"])
axs[1, 0].set_title("Box Plot of Paired Samples")
# 显示W统计量和p值
axs[1, 1].text(0.1, 0.5, f"Wilcoxon Statistic: {w_stat:.2f}\np-value: {p_value:.4f}", fontsize=14)
axs[1, 1].set_axis_off()
plt.tight_layout()
plt.show()