正文
15 方差分析
15.1 方差分析概述
通过对实验数据进行分析, 检验方差相同 的多个正态总体均值 是否相等
实例: 为了对几个行业的服务质量进行评价, 消费者协会在 4 个行业中分别抽取了不同的企业作为样本.最近一年中消费者总共对 23 家企业投诉的次数如下表所示
1 2 3 4 5 6 7 8 9 10 11 12 13 import numpy as npimport pandas as pd data = np.array([[57 , 68 , 31 , 44 ], [66 , 39 , 49 , 51 ], [49 , 29 , 21 , 65 ], [40 , 45 , 34 , 77 ], [34 , 56 , 40 , 58 ], [53 , 51 , None , None ], [44 , None , None , None ]]) df = pd.DataFrame(data, index=range (1 , 8 ), columns=["零售业" , "旅游业" , "航空业" , "家电制造业" ]) df.index.name = "观测值" df
零售业
旅游业
航空业
家电制造业
观测值
1
57
68
31
44
2
66
39
49
51
3
49
29
21
65
4
40
45
34
77
5
34
56
40
58
6
53
51
None
None
7
44
None
None
None
1 2 3 4 5 6 7 8 9 10 11 12 13 import matplotlib.pyplot as plt plt.rcParams['font.sans-serif' ]=['SimHei' ] plt.rcParams['axes.unicode_minus' ] = False plt.figure()for i in range (data.shape[1 ]): plt.scatter(i * np.ones(data.shape[0 ]), data.T[i]) plt.xticks(range (data.shape[1 ]), ('零售业' , '旅游业' , '航空业' , '家电制造业' )) plt.ylabel('被投诉次数' ) plt.xlabel('行业' ) plt.show()
从散点图中可以看出, 不同行业被投诉的次数的均值是有差异的, 但这种差异也可能是由抽样的随机性 造成的, 需要有更准确的方法来检验这种差异是否显著
15.2 方差的比较
组内方差: 某一因素的同一 水平(同一个总体)下样本数据的方差, 例如, 零售业被投诉次数的方差. 组内方差只包含随机误差
组间方差: 某一因素的不同 水平(不同总体)下个样本之间的方差, 例如, 4 个行业被投诉次数之间的方差. 组间方差既包含随机误差 , 也包含系统误差
如果不同行业对投诉次数没有影响, 则组间误差中只 包含随机误差, 没有系统误差, 此时组件误差与组内误差经过平均后的数值很接近, 它们的比值会接近于 1
如果不同行业对投诉次数有影响, 在组间误差中除包含随机误差之外, 还 会包含系统误差, 此时它们的比值会大于 1
15.3 方差分析
15.3.1 单因素方差分析
与方差分析相关的统计量:
1 水平(总体)的均值
X ¯ i = 1 n i Σ j = 1 n i X i j , i = 1 , . . . , k \bar X_i=\frac{1}{n_i}\Sigma^{n_i}_{j=1}X_{ij}, i=1,...,k
X ¯ i = n i 1 Σ j = 1 n i X i j , i = 1 , . . . , k
1 2 3 4 X_bar = []for i in range (data.shape[1 ]): X_bar.append(data.T[i][data.T[i] != np.array(None )].mean()) X_bar
[49.0, 48.0, 35.0, 59.0]
2 全部观察值的总均值
全部观察值X i j X_ij X i j 的总和 除以 观察值的个数
X ¯ ¯ = 1 n Σ i = 1 k Σ j = 1 n i X i j = 1 n Σ i = 1 k n i X i ¯ \bar{\bar{X}}=\frac{1}{n}\Sigma^k_{i=1}\Sigma^{n_i}_{j=1}X_{ij}=\frac{1}{n}\Sigma^k_{i=1}n_i\bar{X_i}
X ¯ ¯ = n 1 Σ i = 1 k Σ j = 1 n i X i j = n 1 Σ i = 1 k n i X i ¯
1 2 X_bar_bar = data.T[data.T != np.array(None )].mean() X_bar_bar
47.869565217391305
3 总离差平方和(SST)
样本全部观察值X i j X_{ij} X i j 与总平均值X ¯ ¯ \bar{\bar X} X ¯ ¯ 的离差平方和, 反映全部观察值的离散情况.
S S T = Σ i = 1 k Σ j = 1 n i ( X i j − X ¯ ¯ ) 2 SST=\Sigma^k_{i=1}\Sigma^{n_i}_{j=1}(X_{ij}- \bar{\bar X})^2
S S T = Σ i = 1 k Σ j = 1 n i ( X i j − X ¯ ¯ ) 2
1 2 SST = ((data.T[data.T != np.array(None )] - X_bar_bar) ** 2 ).sum () SST
4164.608695652174
4 水平项平方和(SSA)
各个水平A i A_i A i 下样本均值X ¯ i \bar X_i X ¯ i 与样本总平均X ¯ ¯ \bar{\bar X} X ¯ ¯ 的偏差平方和, 它在一定程度上反映了各总体均值μ j \mu_j μ j 之间的差异引起的波动, 又称组间平方和, 该平方和既包括随机误差, 也包括系统误差
S S A = Σ i = 1 k Σ j = 1 n i ( X ¯ i − X ¯ ¯ ) 2 = Σ i = 1 k n i ( X ¯ i − X ¯ ¯ ) 2 SSA=\Sigma^k_{i=1}\Sigma^{n_i}_{j=1}(\bar X_i-\bar{\bar X})^2=\Sigma^k_{i=1}n_i(\bar X_i-\bar{\bar X})^2
S S A = Σ i = 1 k Σ j = 1 n i ( X ¯ i − X ¯ ¯ ) 2 = Σ i = 1 k n i ( X ¯ i − X ¯ ¯ ) 2
1 2 3 4 5 SSA = 0 for i in range (data.shape[1 ]): SSA += len (data.T[i][data.T[i] != np.array(None )]) *\ (data.T[i][data.T[i] != np.array(None )].mean() - X_bar_bar) ** 2 SSA
1456.608695652174
5 误差项平方和(SSE)
在各个总体A i A_i A i 下, 样本数据X i j X_{ij} X i j 与其总体均值X ¯ i \bar X_i X ¯ i 的偏差平方和反映了抽样的随机性引起的样本数据X i j X_{ij} X i j 的波动, 又称组内平方和, 该平方和反映的是随机误差的大小
S S E = Σ i = 1 k Σ j = 1 n i ( X i j − X i ¯ ) 2 SSE=\Sigma^k_{i=1}\Sigma^{n_i}_{j=1}(X_{ij}-\bar{X_i})^2
S S E = Σ i = 1 k Σ j = 1 n i ( X i j − X i ¯ ) 2
1 2 3 4 5 SSE = 0 for i in range (data.shape[1 ]): for j in data.T[i][data.T[i] != np.array(None )]: SSE += (j - X_bar[i]) ** 2 SSE
2708.0
6 总离差平方和的分解
S S T = S S E + S S A SST=SSE+SSA
S S T = S S E + S S A
7 各自由度
S S T SST S S T 的自由度为n − 1 n-1 n − 1 , 其中n n n 为全部观察值的个数
误差项离差平方和(S S E SSE S S E )的自由度为k − 1 k-1 k − 1 , 其中k k k 为因素水平(总体)的个数
水平项离差平方和(S S A SSA S S A )的自由度为n − k n-k n − k
8 各误差的均方差 MSA 和 MSE
组间方差S S A SSA S S A 的均方差记为M S A MSA M S A
组内方差S S E SSE S S E 的均方差记为M S E MSE M S E
计算方法是用误差平方 除以 相应的自由度
设置检验统计量
F = S S A / ( k − 1 ) S S E / ( n − k ) = M S A M S E F ( k − 1 , n − k ) F=\frac{SSA/(k-1)}{SSE/(n-k)}=\frac{MSA}{MSE}F(k-1, n-k)
F = S S E / ( n − k ) S S A / ( k − 1 ) = M S E M S A F ( k − 1 , n − k )
1 2 3 4 k = len (data[1 ]) n = len (data[data!= np.array(None )]) F = (SSA / (k - 1 )) / (SSE / (n - k)) F
3.4066426904716036
上述分析的结果可排成表格的形式, 称为单因素实验方差分析表:
方差来源
误差平方和
自由度
均方差
F 值
组间
SSA
k-1
MSA
MSA/MSE
组内
SSE
n-k
MSE
总和
SST=SSE+SSA
n-1
15.3.2 方差分析中的多重比较
为了进一步了解因素 A 的各个总体对观测变量的具体影响效果
多重比较检验就是通过对各个总体观测变量均值的逐对 比较, 来进一步检验到底哪些均值之间存在差异, 并找出最优水平.
如果原假设H 0 : μ i = μ j , i , j = 1 , 2 , . . . , r , i ≠ j H_0:\mu_i=\mu_j,i,j=1,2,...,r,i\ne j H 0 : μ i = μ j , i , j = 1 , 2 , . . . , r , i ≠ j 成立, 检验统计量应较小, 因此拒绝域为∣ X ¯ i − X ¯ j ∣ > t α / 2 M S E ( 1 n i + 1 n j ) |\bar X_i-\bar X_j|>t_{\alpha/2}\sqrt{MSE(\frac{1}{n
_i}+\frac{1}{n_j})} ∣ X ¯ i − X ¯ j ∣ > t α / 2 √ M S E ( n i 1 + n j 1 )
如果满足拒绝域条件, 则认为μ i \mu_i μ i 与μ j \mu_j μ j 有显著性差异, 否则认为它们之间没有显著性差异
例 15.2
1 2 3 4 5 6 7 8 9 10 11 import pandas as pdimport numpy as np data = np.array([[26.5 , 31.2 , 27.9 , 30.8 ], [28.7 , 28.3 , 25.1 , 29.6 ], [25.1 , 30.8 , 28.5 , 32.4 ], [29.1 , 27.9 , 24.2 , 31.7 ], [27.2 , 29.6 , 26.5 , 32.8 ]]) df = pd.DataFrame(data, index=range (1 , 6 ), columns=["无色" , "粉色" , "橘黄色" , "绿色" ]) df.index.name = "样本" df
无色
粉色
橘黄色
绿色
样本
1
26.5
31.2
27.9
30.8
2
28.7
28.3
25.1
29.6
3
25.1
30.8
28.5
32.4
4
29.1
27.9
24.2
31.7
5
27.2
29.6
26.5
32.8
1 2 3 4 X_bar = []for i in data.T: X_bar.append(np.round (i.mean(), 2 )) X_bar
[27.32, 29.56, 26.44, 31.46]
1 2 3 4 5 SSE = 0 for i in range (data.shape[1 ]): for j in data.T[i][data.T[i] != np.array(None )]: SSE += (j - X_bar[i]) ** 2 SSE
39.083999999999975
1 2 3 4 n = data.size k = data.shape[1 ] MSE = SSE / (n - k) MSE
2.4427499999999984
令显著性水平α = 0 . 0 5 , t α / 2 ( 1 6 ) = 2 . 1 2 , n i = n j = 5 , i , j = 1 , 2 , 3 , 4 , 5 \alpha=0.05,t_{\alpha/2}(16)=2.12,n_i=n_j=5,i,j=1,2,3,4,5 α = 0 . 0 5 , t α / 2 ( 1 6 ) = 2 . 1 2 , n i = n j = 5 , i , j = 1 , 2 , 3 , 4 , 5
t α / 2 M S E ( 1 n i + 1 n j ) = 2 . 0 9 6 t_{\alpha/2}\sqrt{MSE(\frac{1}{n_i}+\frac{1}{n_j})}=2.096 t α / 2 √ M S E ( n i 1 + n j 1 ) = 2 . 0 9 6
1 2 3 4 5 from scipy.stats import t alpha = 0.05 t_alpha_div_2 = t.ppf(1 - alpha / 2 , (n - k)) t_alpha_div_2
2.1199052992210112
1 np.round (t_alpha_div_2 * np.sqrt(MSE * (1 / data.shape[0 ] + 1 / data.shape[0 ])), 3 )
2.095
1 2 3 for i in range (len (X_bar) - 1 ): for j in range (i + 1 , len (X_bar)): print ("|\\bar X_{} - \\bar X_{}| ={})" .format (i + 1 , j + 1 , np.round (np.abs (X_bar[i]-X_bar[j]), 2 )))
|\bar X_1 - \bar X_2| =2.24)
|\bar X_1 - \bar X_3| =0.88)
|\bar X_1 - \bar X_4| =4.14)
|\bar X_2 - \bar X_3| =3.12)
|\bar X_2 - \bar X_4| =1.9)
|\bar X_3 - \bar X_4| =5.02)
依据上面结果可得出相应的影响效果,
如∣ X ¯ 1 − X ¯ 2 ∣ > 2 . 0 9 5 |\bar X_1 - \bar X_2|>2.095 ∣ X ¯ 1 − X ¯ 2 ∣ > 2 . 0 9 5 , 则说明X 1 X_1 X 1 和X 2 X_2 X 2 有显著性差异, 也就是说明无色和粉色对产品销售的影响有显著性差异
∣ X ¯ 2 − X ¯ 4 ∣ < 2 . 0 9 5 |\bar X_2 - \bar X_4|<2.095 ∣ X ¯ 2 − X ¯ 4 ∣ < 2 . 0 9 5 , 说明X 2 X_2 X 2 和X 4 X_4 X 4 没有显著性差异, 也就是说粉色和绿色对产品销售的影响没有显著性差异
15.3.3 多因素方差分析
方差来源
误差平方和
自由度
均方差 MS
F 值
因素 A
S S A SSA S S A
s − 1 s-1 s − 1
M S A = S S A s − 1 MSA=\frac{SSA}{s-1} M S A = s − 1 S S A
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
因素 B
S S B SSB S S B
r − 1 r-1 r − 1
M S B = S S B r − 1 MSB=\frac{SSB}{r-1} M S B = r − 1 S S B
F B = M S B M S E F_B=\frac{MSB}{MSE} F B = M S E M S B
因素 AB 交互作用
S S A B SSAB S S A B
( r − 1 ) ( s − 1 ) (r-1)(s-1) ( r − 1 ) ( s − 1 )
M S A B = S S A B ( r − 1 ) ( s − 1 ) MSAB=\frac{SSAB}{(r-1)(s-1)} M S A B = ( r − 1 ) ( s − 1 ) S S A B
F A B = M S A B M S E F_{AB}=\frac{MSAB}{MSE} F A B = M S E M S A B
误差
S S E SSE S S E
r s ( m − 1 ) rs(m-1) r s ( m − 1 )
M S E = S S E r s ( m − 1 ) MSE=\frac{SSE}{rs(m-1)} M S E = r s ( m − 1 ) S S E
总和
S S T SST S S T
r s m − 1 rsm-1 r s m − 1
统计量
服从分布
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
[ s − 1 , r s ( m − 1 ) ] \left[s-1,rs(m-1)\right] [ s − 1 , r s ( m − 1 ) ]
15.3.3 多因素方差分析
方差来源
误差平方和
自由度
均方差 MS
F 值
因素 A
S S A SSA S S A
s − 1 s-1 s − 1
M S A = S S A s − 1 MSA=\frac{SSA}{s-1} M S A = s − 1 S S A
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
因素 B
S S B SSB S S B
r − 1 r-1 r − 1
M S B = S S B r − 1 MSB=\frac{SSB}{r-1} M S B = r − 1 S S B
F B = M S B M S E F_B=\frac{MSB}{MSE} F B = M S E M S B
因素 AB 交互作用
S S A B SSAB S S A B
( r − 1 ) ( s − 1 ) (r-1)(s-1) ( r − 1 ) ( s − 1 )
M S A B = S S A B ( r − 1 ) ( s − 1 ) MSAB=\frac{SSAB}{(r-1)(s-1)} M S A B = ( r − 1 ) ( s − 1 ) S S A B
F A B = M S A B M S E F_{AB}=\frac{MSAB}{MSE} F A B = M S E M S A B
误差
S S E SSE S S E
r s ( m − 1 ) rs(m-1) r s ( m − 1 )
M S E = S S E r s ( m − 1 ) MSE=\frac{SSE}{rs(m-1)} M S E = r s ( m − 1 ) S S E
总和
S S T SST S S T
r s m − 1 rsm-1 r s m − 1
统计量
服从分布
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
[ s − 1 , r s ( m − 1 ) ] \left[s-1,rs(m-1)\right] [ s − 1 , r s ( m − 1 ) ]
15.3.3 多因素方差分析
方差来源
误差平方和
自由度
均方差 MS
F 值
因素 A
S S A SSA S S A
s − 1 s-1 s − 1
M S A = S S A s − 1 MSA=\frac{SSA}{s-1} M S A = s − 1 S S A
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
因素 B
S S B SSB S S B
r − 1 r-1 r − 1
M S B = S S B r − 1 MSB=\frac{SSB}{r-1} M S B = r − 1 S S B
F B = M S B M S E F_B=\frac{MSB}{MSE} F B = M S E M S B
因素 AB 交互作用
S S A B SSAB S S A B
( r − 1 ) ( s − 1 ) (r-1)(s-1) ( r − 1 ) ( s − 1 )
M S A B = S S A B ( r − 1 ) ( s − 1 ) MSAB=\frac{SSAB}{(r-1)(s-1)} M S A B = ( r − 1 ) ( s − 1 ) S S A B
F A B = M S A B M S E F_{AB}=\frac{MSAB}{MSE} F A B = M S E M S A B
误差
S S E SSE S S E
r s ( m − 1 ) rs(m-1) r s ( m − 1 )
M S E = S S E r s ( m − 1 ) MSE=\frac{SSE}{rs(m-1)} M S E = r s ( m − 1 ) S S E
总和
S S T SST S S T
r s m − 1 rsm-1 r s m − 1
统计量
服从分布
F A = M S A M S E F_A=\frac{MSA}{MSE} F A = M S E M S A
[ s − 1 , r s ( m − 1 ) ] \left[s-1,rs(m-1)\right] [ s − 1 , r s ( m − 1 ) ]
F B = M S B M S E F_B=\frac{MSB}{MSE} F B = M S E M S B
[ r − 1 , r s ( m − 1 ) ] \left[r-1,rs(m-1)\right] [ r − 1 , r s ( m − 1 ) ]
F A B = M S A B M S E F_{AB}=\frac{MSAB}{MSE} F A B = M S E M S A B
[ ( r − 1 ) ( s − 1 ) , r s ( m − 1 ) ] \left[(r-1)(s-1),rs(m-1)\right] [ ( r − 1 ) ( s − 1 ) , r s ( m − 1 ) ]
m 为试验次数(≥ 2 \ge2 ≥ 2 )
例 15.3
有s = 4 s=4 s = 4 个品牌的彩电在r = 5 r=5 r = 5 个地区销售, 为分析品牌和地区对销售量是否有影响, 每个品牌在各个地区的销售量如下, 试分析品牌和地区对销售量是否有显著影响?( α = 0 . 0 5 ) (\alpha=0.05) ( α = 0 . 0 5 )
1 2 3 4 5 6 7 8 9 10 11 12 import numpy as npimport pandas as pd data = np.array([[365 , 350 , 343 , 340 , 323 ], [345 , 368 , 363 , 330 , 333 ], [358 , 323 , 353 , 343 , 308 ], [288 , 280 , 298 , 260 , 298 ]]) df = pd.DataFrame(data, columns=["B1" , "B2" , "B3" , "B4" , "B5" ], index=["A1" , "A2" , "A3" , "A4" ]) df.index.name = "品牌销售表(因素 A)" df.columns.name = "销售地区(因素 B)" df
销售地区(因素 B)
B1
B2
B3
B4
B5
品牌销售表(因素 A)
A1
365
350
343
340
323
A2
345
368
363
330
333
A3
358
323
353
343
308
A4
288
280
298
260
298
S S T = 3 6 5 2 + 3 5 0 2 + . . . + 2 9 8 2 − 6 5 6 9 2 2 0 = 1 7 8 8 8 . 9 5 SST=365^2+350^2+...+298^2-\frac{6569^2}{20}=17888.95 S S T = 3 6 5 2 + 3 5 0 2 + . . . + 2 9 8 2 − 2 0 6 5 6 9 2 = 1 7 8 8 8 . 9 5
1 2 SST = (data ** 2 ).sum () - data.sum () ** 2 / data.size SST
17888.950000000186
S S A = 1 5 ( 1 7 2 1 2 + 1 7 3 9 2 + . . . + 1 4 2 4 2 ) − 6 5 6 9 2 2 0 = 1 3 0 0 4 . 5 5 SSA=\frac{1}{5}(1721^2+1739^2+...+1424^2)-\frac{6569^2}{20}=13004.55 S S A = 5 1 ( 1 7 2 1 2 + 1 7 3 9 2 + . . . + 1 4 2 4 2 ) − 2 0 6 5 6 9 2 = 1 3 0 0 4 . 5 5
1 2 3 4 5 6 SSA = 0 for i in data: SSA += i.sum () ** 2 SSA /= data.shape[1 ] SSA -= data.sum () ** 2 / data.size SSA
13004.55000000028
S S B = 1 4 ( 1 3 5 6 2 + 1 3 2 1 2 + . . . + 1 2 6 2 2 ) − 6 5 6 9 2 2 0 = 2 0 1 1 . 7 SSB=\frac{1}{4}(1356^2+1321^2+...+1262^2)-\frac{6569^2}{20}=2011.7 S S B = 4 1 ( 1 3 5 6 2 + 1 3 2 1 2 + . . . + 1 2 6 2 2 ) − 2 0 6 5 6 9 2 = 2 0 1 1 . 7
1 2 3 4 5 6 SSB = 0 for i in data.T: SSB += i.sum () ** 2 SSB /= data.shape[0 ] SSB -= data.sum () ** 2 / data.size SSB
2011.7000000001863
S S E = S S T − S S A − S S B = 2 8 7 2 . 7 SSE=SST-SSA-SSB=2872.7 S S E = S S T − S S A − S S B = 2 8 7 2 . 7
1 2 SSE = SST - SSA - SSB SSE
2872.6999999997206
差异源
平方和
自由度
均方
F 值
品牌(因素 A)
SSA = 13004.55
s - 1 = 3
MSA = SSA / (s - 1) = 4334.85
MSA / MSE = 18.10777
地区(因素 B)
SSB = 2011.7
r - 1 = 4
MSB = SSB / (r - 1) = 502.925
MSB / MSE = 2.100846
误差
SSE = 2872.7
(r - 1)(s - 1) = 12
MSE = SSE / (rs(m - 1)) = 239.3917
总和
SST = SSA + SSB + SSE = 17888.95
rsm - 1 = 19
由于F A = 1 8 . 1 0 8 > F 0 . 9 5 ( 3 , 1 2 ) = 3 . 4 9 F_A=18.108>F_{0.95}(3, 12)=3.49 F A = 1 8 . 1 0 8 > F 0 . 9 5 ( 3 , 1 2 ) = 3 . 4 9 , 说明彩电的品牌对销售量有显著影响
由于F B = 2 . 1 0 1 < F 0 . 9 5 ( 4 , 1 2 ) = 3 . 2 6 F_B=2.101<F_{0.95}(4, 12)=3.26 F B = 2 . 1 0 1 < F 0 . 9 5 ( 4 , 1 2 ) = 3 . 2 6 , 说明销售地区对彩电的销售没有显著影响
15.4 综合实例——连锁餐饮用户评级分析
15.4.1 单因素方差实例分析
某连锁餐饮在 3 个城市用户评分资料如表所示,已知各城市用户评分的分布近似与正态等方差,是以 95%的可靠性判断城市对用户评分是否有显著影响?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from scipy.stats import f_onewayimport scipy.stats as statsimport numpy as npimport pandas as pdfrom statsmodels.formula.api import olsfrom statsmodels.stats.anova import anova_lm cityA = [10 ,9 ,9 ,8 ,8 ,7 ,7 ,8 ,8 ,9 ] cityB = [10 ,8 ,9 ,8 ,7 ,7 ,7 ,8 ,9 ,9 ] cityC = [9 ,9 ,8 ,8 ,8 ,7 ,6 ,9 ,8 ,9 ] df = pd.DataFrame(np.vstack((cityA, cityB, cityC)), index=['A' , 'B' , 'C' ]) df.columns.name = "用户评分" df.index.name = "城市" df
用户评分
0
1
2
3
4
5
6
7
8
9
城市
A
10
9
9
8
8
7
7
8
8
9
B
10
8
9
8
7
7
7
8
9
9
C
9
9
8
8
8
7
6
9
8
9
方法 1 使用 scipy.stats.f_oneway()方法
1 2 3 4 5 6 7 8 9 """ scipy.stats.levene(*samples, center='median', proportiontocut=0.05) 对等方差执行 Levene 检验。 小的 p-value 表明总体没有相等的方差。 """ (W, p) = stats.levene(cityA, cityB, cityC)if p < 0.05 : print (('Warning: the p-value of the Levene test is <0.05: p = {0}' .format (p)))
1 2 3 4 5 6 F_statistic, pVal = stats.f_oneway(cityA, cityB, cityC)print ('单因素方差分析结果(f_oneway): F = {0}, and p = {1}' .format (F_statistic, pVal))if pVal < 0.05 : print ('One of the groups is significantly different.' )
单因素方差分析结果(f_oneway): F = 0.10150375939849626, and p = 0.9038208903685354
方法 2 利用 statsmodels 库函数中包含的 anova_lm 模型, 使用线性 OLSModel 进行方差分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 df = pd.DataFrame() names = locals ()for city in ['A' ,'B' ,'C' ]: s = names['city%c' % city] df_temp = pd.DataFrame({'city' :city[-1 ], 'S' :s}) df = pd.concat([df, df_temp], ignore_index=True ) model = ols('S ~ city' , df).fit() anovaResults = anova_lm(model)print ('单因素方差分析结果(anova_lm):' )print (anovaResults) df
单因素方差分析结果(anova_lm):
df sum_sq mean_sq F PR(>F)
city 2.0 0.2 0.100000 0.101504 0.903821
Residual 27.0 26.6 0.985185 NaN NaN
city
S
0
A
10
1
A
9
2
A
9
3
A
8
4
A
8
5
A
7
6
A
7
7
A
8
8
A
8
9
A
9
10
B
10
11
B
8
12
B
9
13
B
8
14
B
7
15
B
7
16
B
7
17
B
8
18
B
9
19
B
9
20
C
9
21
C
9
22
C
8
23
C
8
24
C
8
25
C
7
26
C
6
27
C
9
28
C
8
29
C
9
3 手动计算各误差值, 实现单因素方差分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from scipy.stats import f_onewayimport scipy.stats as statsimport numpy as npimport pandas as pd cityA = [10 ,9 ,9 ,8 ,8 ,7 ,7 ,8 ,8 ,9 ] cityB = [10 ,8 ,9 ,8 ,7 ,7 ,7 ,8 ,9 ,9 ] cityC = [9 ,9 ,8 ,8 ,8 ,7 ,6 ,9 ,8 ,9 ] df = pd.DataFrame() names = locals ()for city in ['A' ,'B' ,'C' ]: s = names['city%c' % city] df_temp = pd.DataFrame({'city' :city[-1 ], 'S' :s}) df = pd.concat([df, df_temp], ignore_index=True ) groups = df.groupby('city' ) ss_total = np.sum ((df['S' ] - df['S' ].mean()) ** 2 ) (ss_treatments, ss_error) = (0 , 0 )for val, group in groups: ss_error += sum ((group['S' ] - group['S' ].mean()) ** 2 ) ss_treatments += len (group) * (group['S' ].mean() - df['S' ].mean()) ** 2 df_groups = len (groups) - 1 df_residuals = len (df) - len (groups) F = (ss_treatments / df_groups) / (ss_error / df_residuals) df = stats.f(df_groups, df_residuals) p = df.sf(F)print (('单因素方差分析结果(手动计算): F = {0}, and p = {1}' .format (F, p)))
单因素方差分析结果(手动计算): F = 0.1015037593984973, and p=0.9038208903685354
由于F < F 0 . 0 5 ( 2 , 2 7 ) = 3 . 3 5 F<F_{0.05}(2, 27)=3.35 F < F 0 . 0 5 ( 2 , 2 7 ) = 3 . 3 5 或P > 0 . 0 5 P>0.05 P > 0 . 0 5 , 所以原假设成立, 不能认为城市对用户评分有影响
15.4.2 多因素方差分析实例
收集在环境等级(environment)和食材等级(ingredients)两个因素影响下的某连锁餐饮店的用户评价数据
1 2 3 4 5 6 7 8 9 10 11 12 from scipy import statsimport pandas as pdimport numpy as npfrom statsmodels.formula.api import olsfrom statsmodels.stats.anova import anova_lm environmental = [5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ] ingredients = [5 ,4 ,3 ,2 ,1 ,5 ,4 ,3 ,2 ,1 ,5 ,4 ,3 ,2 ,1 ,5 ,4 ,3 ,2 ,1 ,5 ,4 ,3 ,2 ,1 ] score = [5 ,5 ,4 ,3 ,2 ,5 ,4 ,4 ,3 ,2 ,4 ,4 ,3 ,3 ,2 ,4 ,3 ,2 ,2 ,2 ,3 ,3 ,3 ,2 ,1 ] data = {'E' :environmental, 'I' :ingredients, 'S' :score} df = pd.DataFrame(data) df
E
I
S
0
5
5
5
1
5
4
5
2
5
3
4
3
5
2
3
4
5
1
2
5
4
5
5
6
4
4
4
7
4
3
4
8
4
2
3
9
4
1
2
10
3
5
4
11
3
4
4
12
3
3
3
13
3
2
3
14
3
1
2
15
2
5
4
16
2
4
3
17
2
3
2
18
2
2
2
19
2
1
2
20
1
5
3
21
1
4
3
22
1
3
3
23
1
2
2
24
1
1
1
利用 statsmodels 中的 anova_lm 模块进行多因素方差分析
1 2 3 4 5 6 7 8 """ 符号意义: (~)隔离自变量和因变量(左边因变量, 右边自变量) (+)分离各个自变量 """ formula = 'S~E+I' results = anova_lm(ols(formula,df).fit() )print (results)
df sum_sq mean_sq F PR(>F)
E 1.0 7.22 7.220000 46.444444 7.580723e-07
I 1.0 18.00 18.000000 115.789474 3.129417e-10
Residual 22.0 3.42 0.155455 NaN NaN
由于P 值很小, 说明环境和食材两个因素对用户评分影响较大