统计检验——方差检验(ANOVA)分析变量间的显著性差异
什么是方差检验(ANOVA)
方差检验是一种统计方法,用于比较三个或更多样本组之间的均值差异,以确定这些组是否来自同一个总体,它通过分析组内和组间的变异来评估不同组之间是否存在显著差异
基本概念
- 组间变异:衡量各组均值之间的变异
- 组内变异:衡量每组内部个体之间的差异
- 总变异:组间变异和组内变异的总和
假设
- 各样本是独立的
- 各组的样本来自正态分布总体
- 各组的总体方差相等(同方差性)
类型
- 单因素方差分析:用于比较一个因子下的多个组
- 双因素方差分析:用于比较两个因子及其交互作用下的多个组
步骤设定假设
- 原假设( ):所有组的均值相等
- 备择假设( ):至少有一个组的均值不等
计算平方和
总平方合:
其中, 是第 个观测值, 是所有观测值的总体平均值, 是观测值的总数
组间平方和:
其中, 是组的数量, 是第 组的观测值数量, 是第 组的均值
组内平方和:
其中, 是第 组中第 个观测值, 是第 组的均值
计算自由度
总自由度:
组间自由度:
组内自由度:
计算均方
组间均方:
组内均方:
计算 值
确定显著性水平
根据计算得到的 值和自由度查找 分布表,确定 值,若 值小于显著性水平(如0.05),则拒绝原假设,当然这里一般都是通过软件实现如SPSS、Python等
单因素方差分析实现
代码
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
# 生成模拟数据(假设每组有30个样本)
np.random.seed(0)
fertilizer_a = np.random.normal(20, 5, 30) # 肥料A组的植物高度
fertilizer_b = np.random.normal(22, 5, 30) # 肥料B组的植物高度
fertilizer_c = np.random.normal(23, 5, 30) # 肥料C组的植物高度
# 单因素方差分析
f_value, p_value = stats.f_oneway(fertilizer_a, fertilizer_b, fertilizer_c)
print(f"F值: {f_value}")
print(f"p值: {p_value}")
# 创建一个包含所有组的 DataFrame
data = {
'height': np.concatenate([fertilizer_a, fertilizer_b, fertilizer_c]),
'fertilizer': ['Fertilizer A']*len(fertilizer_a) +
['Fertilizer B']*len(fertilizer_b) +
['Fertilizer C']*len(fertilizer_c)
}
df = pd.DataFrame(data)
# 使用 seaborn 进行可视化
plt.figure(figsize=(10, 6))
sns.boxplot(x='fertilizer', y='height', data=df)
sns.swarmplot(x='fertilizer', y='height', data=df, color='black', alpha=0.5)
plt.title('Effect of Different Fertilizers on Plant Growth')
plt.xlabel('Fertilizer Type')
plt.ylabel('Plant Height (cm)')
plt.show()
结果解读
使用np.random.normal生成模拟数据,假设每组植物的高度符合正态分布,但均值不同(分别为20、22和23),标准差相同(5),利用箱图展示不同肥料对植物生长的影响,这里 值大于显著性水平(通常为0.05),则认为不同肥料类型对植物生长的影响不显著
单因素方差分析实现
代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
from statsmodels.formula.api import ols
# 生成模拟数据
np.random.seed(0)
num_samples = 15
fertilizer_types = ['Fertilizer A', 'Fertilizer B', 'Fertilizer C']
watering_frequencies = ['Daily', 'Weekly']
data = []
for fertilizer in fertilizer_types:
for watering in watering_frequencies:
# 随机生成植物高度数据
heights = np.random.normal(loc=20 + 2 * fertilizer_types.index(fertilizer) + 5 * (watering == 'Daily'), scale=5, size=num_samples)
for height in heights:
data.append([fertilizer, watering, height])
# 创建 DataFrame
df = pd.DataFrame(data, columns=['Fertilizer', 'Watering', 'Height'])
# 双因素方差分析
model = ols('Height ~ C(Fertilizer) * C(Watering)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
# 使用 seaborn 进行可视化
plt.figure(figsize=(15, 5))
plt.subplot(1,2,1)
# 交互作用图
interaction_plot = sns.pointplot(x='Fertilizer', y='Height', hue='Watering', data=df, markers=["o", "s"], linestyles=["-", "--"])
plt.title('Interaction Plot of Fertilizer Type and Watering Frequency on Plant Height')
plt.xlabel('Fertilizer Type')
plt.ylabel('Plant Height (cm)')
plt.legend(title='Watering Frequency')
plt.subplot(1,2,2)
# 箱线图
sns.boxplot(x='Fertilizer', y='Height', hue='Watering', data=df)
plt.title('Box Plot of Plant Height by Fertilizer Type and Watering Frequency')
plt.xlabel('Fertilizer Type')
plt.ylabel('Plant Height (cm)')
plt.legend(title='Watering Frequency')
plt.show()
背景
研究问题
假设研究不同类型的肥料和不同的灌溉频率对植物生长的影响是否显著?是否存在交互效应?
实验设计
- 因素1(肥料类型):肥料A、肥料B、肥料C
- 因素2(灌溉频率):每天浇水、每周浇水
- 每个组合(肥料类型和灌溉频率)包含15株植物
- 测量每株植物在一个生长周期后的高度(单位:厘米)
结果解读
使用statsmodels库中的ols函数进行线性回归模型拟合,并使用anova_lm进行双因素方差分析,输出的ANOVA表格显示了各个因素(肥料类型、灌溉频率)及其交互作用对植物高度的影响,通过交互作用图,可以直观地看到不同肥料类型和灌溉频率的组合对植物高度的影响,箱线图展示了每种组合下植物高度的分布和离群值,便于比较不同组之间的差异,接下来我们对ANOVA表格进行详细的解读:
- C(Fertilizer)肥料类型的 值 = 0.100716 > 0.05意味着肥料类型对植物高度的影响不显著,不同肥料之间的差异不大,不能得出肥料类型对植物高度有显著影响的结论
- C(Watering)灌溉频率的 值 = 0.000002 < 0.05意味着灌溉频率对植物高度有显著影响,每天浇水与每周浇水对植物生长有显著不同的效果
- C(Fertilizer)肥料类型与灌溉频率交互作用的 值 = 0.267650 > 0.05意味着肥料类型与灌溉频率之间的交互作用不显著,肥料和灌溉的影响是独立的,没有显著的交互效应
根据这些结果,我们可以建议关注灌溉频率对植物生长的显著影响,而肥料类型和其与灌溉频率的交互作用在本次实验中没有显著影响结束语通过本次对单因素方差分析和双因素方差分析的介绍及实践,了解如何利用统计方法评估不同因素及其交互作用对实验结果的影响,其实在机器学习上也会引入方差分析进行特征选择参考文章特征筛选(过滤法)—— ANOVA ,这样的方法帮助我们理解哪些特征对目标变量有显著影响,从而优化模型性能
本文章转载微信公众号@Python机器学习AI