如下图所示,ABCD四个区域在不同日期的销售数据:
问题一:每个地区间的销售量是否相同?
问题二:不同月份的销售是否相同?
问题三:不同时间与地区的销售量是否相同?
Excel解答三个问题:
答一:
P=0.0249<0.05,故拒绝原假设。同理F=3.466>2.838,拒绝原假设。我们认为每个地区的销量是不同的。
答二:
P=0.106>0.05,不能拒绝原假设。同理F=2.368<3.225,不能拒绝原假设,不同月份销量是相同的。
答三:
不同时间对销售量无显著影响,而不同地区对销售量是有显著影响的。
Python解答:
import pandas as pd
import numpy as np
data = pd.read_excel("D:\pyFile\销售数据.xlsx")
#print(data)
#构建单因素方差分析
def one_way_anova(data,F):
r,c = data.shape
df_ssa = c - 1
df_sse = r*c - c
data_mean = data.values.mean() #总均值
ssa = 0
sse = 0
for i in range(c):
#每组数据
data_group = data.iloc[:,i].values
#组间误差
ssa += len(data_group) * ((data_group.mean() - data_mean)**2)
for j in data_group:
#组内误差
sse += (j - data_group.mean())**2
msa = round(ssa/df_ssa,2)
mse = round(sse/df_sse,2)
if msa/mse > F:
print(msa/mse)
print('拒绝原假设')
else:
print(msa/mse)
print('接受原假设')
#构建无交互作用的双因素方差分析
def two_way_anova(data,Fr,Fc):
r,c = data.shape
df_sst = r*c-1 #总自由度
df_ssc = c-1 #组间自由度(列)
df_ssr = r-1 #组间自由度(行)
df_sse = (c-1)*(r-1) #组内自由度(行)
data_mean = data.values.mean()
ssr = 0
ssc = 0
sst = 0
for i in range(c): #组间(列)误差
data_cgroup = data.iloc[:,i].values
ssc += len(data_cgroup)*((data_cgroup.mean()-data_mean)**2)
for j in range(r): #组间(行)误差
data_rgroup = data.iloc[j,:].values
ssr += len(data_rgroup)*((data_rgroup.mean()-data_mean)**2)
sst = np.sum([(k-data.values.mean())**2 for k in data.values]) #总误差
sse = sst - ssr -ssc
msr = round(ssr/df_ssr,2)
msc = round(ssc/df_ssc,2)
mse = round(sse/df_sse,2)
if msr/mse > Fr:
print(msr/mse)
print('行因素拒绝原假设')
else:
print(msr/mse)
print('行因素不能拒绝原假设')
if msc/mse > Fc:
print(msc/mse)
print('列因素拒绝原假设')
else:
print(msc/mse)
print('列因素不能拒绝原假设')
one_way_anova(data,2.84)
out:
3.466423904557266
拒绝原假设
two_way_anova(data,2.16,2.92)
out:
1.6070617016801232
行因素不能拒绝原假设
3.9925072049114414
列因素拒绝原假设
当然,强大如python,不可能没有封装好的函数进行方差分析,可以直接调用scipy.stats.f_oneway进行单因素方差分析,而双因素方差分析需先构建线性回归模型再进行双因素方差分析。
#单因素方差分析
from scipy import stats
stats.f_oneway(data.iloc[:,0],data.iloc[:,1],data.iloc[:,2],data.iloc[:,3])
out:
F_onewayResult(statistic=3.4664239064514066, pvalue=0.024913351378399826)
#双因素方差分析
import statsmodels.api as sm
from statsmodels.formula.api import ols
#构建无交互作用的线性回归模型
model = ols('num ~ C(area) + C(time)', data=data).fit()
#构建交互作用的线性回归模型
model = ols('num ~ C(area) + C(time) + C(area)*C(time)', data=data).fit()
#双因素方差分析
sm.stats.anova_lm(model)
参考:微信公众号"小文的数据之旅"