方差分析(Analysis of Variance,简称ANOVA),又称“变异数分析”或“F检验”,用于两个及两个以上样本均数差别的显著性检验。单因素方差分析即影响试验的因素只有一个。
将抗生素注入人体会产生抗生素与血浆蛋白质结合的现象,这种结合会降低药效。下表给出了四种常用的抗生素注入到牛的体内时,抗生素与血浆蛋白质结合的百分比。推断不同抗生素的结合百分比是否有显著性差异(设显著性水平为0.05)。
抗生素 | 结合百分比 |
---|---|
A1 | 29.6 , 24.3 , 28.5 , 32.0 , 28.6 , 31.5 , 25.7 |
A2 | 27.3 , 32.6 , 30.8 , 34.8 , 31.4 |
A3 | 21.6 , 17.5 , 18.3 , 19.0 , 23.4 , 14.8 |
A4 | 29.2 , 32.8 , 25.0 , 24.2 , 28.2 , 27.4 |
将数据导入Python:
dic_t=[{'抗生素':'A1','结合百分比':29.6},{'抗生素':'A1','结合百分比':24.3},
{'抗生素':'A1','结合百分比':28.5},{'抗生素':'A1','结合百分比':32.0},
{'抗生素':'A1','结合百分比':28.6},{'抗生素':'A1','结合百分比':31.5},
{'抗生素':'A1','结合百分比':25.7},{'抗生素':'A2','结合百分比':27.3},
{'抗生素':'A2','结合百分比':32.6},{'抗生素':'A2','结合百分比':30.8},
{'抗生素':'A2','结合百分比':34.8},{'抗生素':'A2','结合百分比':31.4},
{'抗生素':'A3','结合百分比':21.6},{'抗生素':'A3','结合百分比':17.5},
{'抗生素':'A3','结合百分比':18.3},{'抗生素':'A3','结合百分比':19.0},
{'抗生素':'A3','结合百分比':23.4},{'抗生素':'A3','结合百分比':14.8},
{'抗生素':'A4','结合百分比':29.2},{'抗生素':'A4','结合百分比':32.8},
{'抗生素':'A4','结合百分比':25.0},{'抗生素':'A4','结合百分比':24.2},
{'抗生素':'A4','结合百分比':28.2},{'抗生素':'A4','结合百分比':27.4},]
df_t=pd.DataFrame(dic_t)
运用Levene方差齐性检验,先对各总体等方差的假设进行检验,代码如下:
def f_homovar(df_c,col_fac,col_sta):
df=df_c.copy()
list_fac=df[col_fac].unique()
for i in list_fac:
df.loc[df[col_fac]==i,col_sta]=abs(df[df[col_fac]==i][col_sta]-df[df[col_fac]==i][col_sta].mean())
r=len(list_fac)
n=df[col_sta].count()
x_bar=df[col_sta].mean()
list_Qa=[]
list_Qw=[]
for i in list_fac:
series_i=df[df[col_fac]==i][col_sta]
xi_bar=series_i.mean()
ni=series_i.count()
list_Qa.append(ni*(xi_bar-x_bar)**2)
list_Qw.append(((series_i-xi_bar)**2).sum())
Sa=sum(list_Qa)/(r-1)
Sw=sum(list_Qw)/(n-r)
F=Sa/Sw
sig=stats.f.sf(F,r-1,n-r)
dic_res=[{'Levene Statistic':F,'df1':r-1,'df2':n-r,'Sig.':sig}]
df_res=pd.DataFrame(dic_res,columns=['Levene Statistic','df1','df2','Sig.'])
return df_res
f_homovar(df_t,'抗生素','结合百分比')
结果如下:
由于p值 Sig.= 0.979 > 0.05,故可以认为各总体方差相等。
接下来进行单因素方差分析,代码如下:
def f_oneway(df_c,col_fac,col_sta):
df=df_c.copy()
list_fac=df[col_fac].unique()
r=len(list_fac)
n=df[col_sta].count()
x_bar=df[col_sta].mean()
list_Qa=[]
list_Qw=[]
for i in list_fac:
series_i=df[df[col_fac]==i][col_sta]
xi_bar=series_i.mean()
ni=series_i.count()
list_Qa.append(ni*(xi_bar-x_bar)**2)
list_Qw.append(((series_i-xi_bar)**2).sum())
Sa=sum(list_Qa)/(r-1)
Sw=sum(list_Qw)/(n-r)
F=Sa/Sw
sig=stats.f.sf(F,r-1,n-r)
df_res=pd.DataFrame(columns=['方差来源','平方和','自由度','均方','F值','Sig.'])
df_res['方差来源']=['组间','组内','总和']
df_res['平方和']=[sum(list_Qa),sum(list_Qw),sum(list_Qa)+sum(list_Qw)]
df_res['自由度']=[r-1,n-r,n-1]
df_res['均方']=[Sa,Sw,'-']
df_res['F值']=[F,'-','-']
df_res['Sig.']=[sig,'-','-']
return df_res
f_oneway(df_t,'抗生素','结合百分比')