业务分析问题:

在日常的分析过程中,经常会遇到一个常见的分析问题,一个指标按照一个维度拆分后,是有差异?

比如:不同渠道的转化率是否存在差异?

哪个高?哪个低?

不同渠道之间的差异,差多少算是有差异?多少又不算差异(约等于)?

如何下定论?

统计问题:

假设我们学过了一些统计学的理论知识,但学完到实际工作中也会遇到一些问题。

比如:我大致知道方差分析是啥,但是怎么用?实际应用场景是啥?

N组数据有显著差异,那每组之间都有差异吗?用什么方法判断?

解题思路:

将上面两个问题整合一下,基本就能互相解决问题了。方差分析是个客观反映一个分类变量维度下,不同类别之间结果指标的差异情况的一个有效手段。直接可以得出结论:是否存在显著差异。

如果不存在差异,则平均水平代表整体水平。

如果存在差异,那需要进一步判断,N个类别两两之间,哪些有差异哪些没有差异。需要用到“多重比较”

在业务分析上,如果存在差异,则需要得出有序的结论,比如ABC平均水平分别是多少,高低如何?结论:A=10%,B=6%,C=5%,A>B>=C,A组显著高于B组,而B组和C组差异不显著。

综上,我自己初步封装了一个函数,能完成上述全部流程,直接产出结果。

参考代码:

#系统
import os
#可视化包
import seaborn as sns
from IPython.display import Image
import pydotplus
import matplotlib.pyplot as plt
sns.set()
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
plt.rcParams['font.sans-serif'] = ['simhei']
plt.rcParams['font.serif'] = ['simhei']
sns.set_style("darkgrid",{"font.sans-serif":['simhei','Droid Sans Fallback']})
#数学包
from scipy import stats
import pandas as pd
import numpy as np
#统计检验
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
from statsmodels.stats.multicomp import MultiComparison
#演示数据集
from sklearn import datasets
#读取
iris=datasets.load_iris()
df_0 = pd.DataFrame(iris.data, columns=['SpealLength','Spealwidth','PetalLength','Petalwidth'])
df_0['target']=iris.target
加载各种包
用iris数据集作演示,读取并转成DataFrame;
# 封装 双变量-单因素方差分析
def my_oneWayAnova(df,cata_name,num_name,alpha_anova=0.05,alpha_tukey=0.05):
df[cata_name]=df[cata_name].astype('str')
s1=df[cata_name]
s2=df[num_name]
fml=num_name+'~C('+cata_name+')'
model = ols(fml,data=df).fit()
anova_table_1 = anova_lm(model, typ = 2).reset_index()
p1=anova_table_1.loc[0,'PR(>F)']
#输出 : 是否相等【不等式序列】
if p1>alpha_anova:
print('组间【无】显著差异')
else:
print('组间【有】显著差异')
#输出不等式
# 输出: 统计结果表(均值,分位数,差异组)
df_p1=df.groupby([cata_name])[num_name].describe()
# 输出: Tudey 多重比较
mc = MultiComparison(df[num_name],df[cata_name])
df_smry = mc.tukeyhsd(alpha=alpha_tukey).summary()
m = np.array(df_smry.data)
df_p2 =pd.DataFrame(m[1:],columns=m[0])
#输出 :分类直接的大小差异显著性
df_p1_sub=df_p1[['mean']].copy()
df_p1_sub.sort_values(by='mean',inplace=True)
output_list=[]
for x in range(1,len(df_p1_sub.index)):
if (df_p2.loc[((df_p2.group1==df_p1_sub.index[x-1])&(df_p2.group2==df_p1_sub.index[x]))|
((df_p2.group1==df_p1_sub.index[x])&(df_p2.group2==df_p1_sub.index[x-1])),
'reject'].iloc[0])=="True":
smb='
else:
smb='<='
if x==1:
output_list.append(df_p1_sub.index[x-1])
output_list.append(smb)
output_list.append(df_p1_sub.index[x])
else:
output_list.append(smb)
output_list.append(df_p1_sub.index[x])
out_sentence=' '.join(output_list)
print(out_sentence)
# 输出: 箱线图
#分布可视化boxplot
plt.figure(figsize=(12, 8))
sns.boxplot(x=cata_name, y=num_name,data=df)#,order=df_p1_sub.index
return df_p1,df_p2

自定义函数,返回两个DataFrame,第一个是分类变量的describe(),第二个是“多重比较”的输出结果。

效果如下:

输出第1部分:

首先打印出两行结论:

此维度下组间是否有差异

从小到大排序。“

本例中,3个类别直接,SpealLength存在显著差异,且“0类”显著小于“1类”显著小于“2类”。

输出第2部分:返回的两个DF示例如下:

第一个是分类变量的describe(),返回了每个类别的均值、分位数等统计指标。


第二个是“多重比较”的输出结果,每行是每个类别两两直接的差异显著性。