安卓做任务赚钱网站/郑州搜狗关键词优化顾问
本文主要对以下指标的计算和解释进行阐述,并使用案例说明,最后利用python编写代码进行计算:
- risk ratios and rate ratios(风险比率和比率比率,RR)
- risk difference and rate difference(风险差异和利率差异, RD)
- attributable proportion (attributable risk percent) for the exposed(风险承担的可占比例(可归属风险百分比), AP)
- population attributable risk(人口归因风险,PAF)
- odds ratio(比率, OR)
我们使用的案例如下,假设一种产品来源于两个营销渠道,我们记录了每个渠道的转化人数和未转化人数(转化可以定义为点击、充值等)
营销渠道 | 转化 | 未转化 | 求和 | 转化率 |
---|---|---|---|---|
渠道A | 159 | 2841 | 3000 | 159/3000=5.30% |
渠道B | 46 | 3454 | 3500 | 46/3500=1.31% |
总计 | 205 | 6295 | 6500 | 205/6500=3.15% |
归因分析指标计算
1:计算Risk Ratio(风险比率)、Rate Ratio(比率)
Risk Ratio(风险比率)通常也称为Rate Ratio(比率),表示一个相对于一个因素B,另一个因素A条件下转化率相对于因素B的转化率的倍数(A,B可以理解为实验组和对照组)。
其中CIeCI_eCIe是渠道A的转化率,CIuCI_uCIu是渠道B的转化率。
营销渠道 | 转化 | 未转化 | 求和 | 转化率 |
---|---|---|---|---|
渠道A | 159 | 2841 | 3000 | 159/3000=5.30% |
不暴露 | 46 | 3454 | 3500 | 46/3500=1.31% |
总计 | 205 | 6295 | 6500 | 205/6500=3.15% |
Risk Ration(RR) = 5.30%/1.31% = 4.04
解释:渠道A的转化率是不暴露组的转化率的4.04倍(Risk Ration(RR)=4.04),同时认为渠道A的转化率相比于比不暴露组的转化率提升了了404%-100%=304%(此处含义是以B为基准,相对的含义)
结论:
- 相对不暴露组的转化率而言,渠道A的转化率是不暴露组的4.04倍
- 相比于不暴露组而言,渠道A的转化率相对于B的转化率提升了304%(并不转化率是真的提升304%,而是在B的基础上提升了304%的B的转转化率)
若我们有多组实验,可以用同样的方法计算
2:计算Risk Difference(风险差异)、Rate Difference(比率差异)
Risk Difference(风险差异)也被称为Rate Difference(比率差异)
其中CIeCI_eCIe是渠道A的转化率,CIuCI_uCIu是不暴露组的转化率。Risk Difference(风险差异)的理解非常直观。就是直观的两个渠道转化率的差异。
由RR与RD的公式可知两者的转换关系为:
RD/CIu=RR−1RD/CI_u=RR-1RD/CIu=RR−1
利用上面例子的数据,计算出RD = 5.30%-1.31%=3.99%。代表了渠道A去渠道B的转化率差异为3.99%。
Risk Ratio与Risk Difference的出发角度不同,Risk Ratio衡量的是
渠道A相对于不暴露组提升了多少,可用于衡量改进的效果,而Risk Difference直接衡量了转化率(收益)提升了多少。Risk Ratio是相对的,Risk Difference是绝对的
3:计算Attribution Proportion
Attribution Proportion(归因分数)表示了该渠道人群中有多少是因为该渠道发生转化的。
利用上面数据。计算出
AP=5.30%−1.31%5.30%=75.28%AP = \frac{5.30\%-1.31\%}{5.30\%} = 75.28\%AP=5.30%5.30%−1.31%=75.28%
如果B代表是未参加渠道展示,则对于计算出的归因分数(Attribution Proportion),可以解释如下:渠道A展示的用户中,有75.28%的用户是因为渠道A的展示而发生了转化。
如果我们对Attribution Proportion的分子、分母同时除以CIuCI_uCIu,则Attribution Proportion公式变为如下形式:
AP=RR−1RRAP = \frac{RR-1}{RR} AP=RRRR−1
我们再利用新公式计算一次,利用上面计算的RR= 4.04,计算出
AP=4.04−14.04=75.28%AP = \frac{4.04-1}{4.04} = 75.28\% AP=4.044.04−1=75.28%
4:计算人口归因分数(PAF)
人口归因分数(PAF) Population Attributable Fraction也称为人群归因危险度PAR(Population Attributable Risk)。表示的是,所有转化人群中,有多少因为一个因素而进行转化的。
最直接的计算方式就是:渠道A转化人群占总转化人群比例*渠道A的AP,在上面例子中,转化人群中,有77.5%的人来自渠道A。因此,我们可以认为总人群中有77.5%*75.28%=58.38%的人是因为渠道A的展示发生了转化。
同时,我们也可以通过如下方式进行计算PAF
其中,PpopP_{pop}Ppop =渠道A人数占总人数比例。
我们利用上面公式进行计算,先计算渠道A人数占总人数比例=3000/6500=0.4615,之后计算PAF:
PAF=0.4615∗(4.04−1)0.4615∗(4.04−1)+1=58.38%PAF = \frac{0.4615*(4.04-1)}{0.4615*(4.04-1)+1} = 58.38\% PAF=0.4615∗(4.04−1)+10.4615∗(4.04−1)=58.38%
计算出的PAF与上面采用直接结算得到结果是相同的。代表了,所有转化人数中,有58.38%的人是因为渠道A的展示发生了转化。
在应用中,因为转化率通常都比较低,因此,我们还可以用几率(Odds Ratio)近似代替RR,来计算每个因子的归因分数。
5:计算几率(Odds Ratio)
上面说到了,可以利用几率(Odds Ratio)近似代替RR,作为RR的估计。Odds Ratio(OR)的计算公式如下:
OR=Y1A/Y1BY2A/Y2BOR= \frac{Y1_A/Y1_B}{Y2_A/Y2_B} OR=Y2A/Y2BY1A/Y1B
其中Y1_A是渠道A的转化人数,Y1_B是不暴露组的转化人数,Y2_A是渠道A的未转化人数, Y2_B是不暴露组的未转化人数。
我们将上面例子数据代入计算得到:
OR=159/462841/3454=4.258OR= \frac{159/46}{2841/3454} =4.258OR=2841/3454159/46=4.258
上面已经计算出RR=4.04。对比计算结果,OR与RR的结果近似。
当用OR代替RR后,AP和PAF的估计如下:
AP=OR−1ORAP = \frac{OR-1}{OR} AP=OROR−1
PAF=Ppop∗(OR−1)Ppop∗(OR−1)+1PAF = \frac{P_{pop}*(OR-1)}{P_{pop}*(OR-1)+1} PAF=Ppop∗(OR−1)+1Ppop∗(OR−1)
我们带入数据进行计算:
AP=4.258−14.258=76.51%AP = \frac{4.258-1}{4.258} =76.51\%AP=4.2584.258−1=76.51%
PAF=0.4615∗(4.258−1)0.4615∗(4.258−1)+1=60.05%PAF = \frac{0.4615*(4.258-1)}{0.4615*(4.258-1)+1} = 60.05\% PAF=0.4615∗(4.258−1)+10.4615∗(4.258−1)=60.05%
其中AP=76.51%代表渠道A的转化用户中有76.51%是因为渠道A展示发生了转化,PAF=60.05%代表了,所有转化用户中,有60.05%是因为渠道A发生了转化。
为什么要利用OR作为RR的近似估计去计算AP和PAF?这主要是因为,在转化率比较低的情况下(现实中转化率通常比较低),OR约等于RR。还有一个原因是,在实际中,有一些未转化人群我们是统计不到的,此时渠道A的转化率和不暴露组的转化率就无法计算,就无法准确计算RR,此时可用OR近似代替。而且在一些归隐分析模型中,例如逻辑回归等,只能通过系数βββ计算出OR,不能直接计算出RR。
归因分析python代码
我们使用上面案例数据,数据有三列,第一列为user_id(主键),第二列为对应的营销渠道,第三列为是否转化。
导入数据后,对数据观察如下:
import pandas as pd
import numpy as npAD_data = pd.read_csv("D:/data/Attribution_test/AD_data.csv")
print(AD_data.head(20))
接下来编写Attribution_Analysis类来进行归因分析:
import pandas as pd
import numpy as npclass Attribution_Analysis:def __init__(self, channel, label, user_id):self.AD_data = pd.DataFrame(np.array([channel, label, user_id]).T, columns=['channel', 'label', 'user_id'])#计算RR def _RR_cul(self):self.RR=[]for chn1, chn2 in self.channel_comb:#计算要对比的两个渠道的转化率rr_value = float(self.AD_count[(self.AD_count['channel']==chn1)&(self.AD_count['label']==1)]['trans_rate'])/float(self.AD_count[(self.AD_count['channel']==chn2)&(self.AD_count['label']==1)]['trans_rate'])self.RR.append(rr_value)print("渠道{0}相对于渠道{1}的风险比率RR为:{2}".format(chn1,chn2,self.RR[-1]))#计算RDdef _RD_cul(self):self.RD = []for chn1, chn2 in self.channel_comb:rd_value = float(self.AD_count[(self.AD_count['channel']==chn1)&(self.AD_count['label']==1)]['trans_rate'])-float(self.AD_count[(self.AD_count['channel']==chn2)&(self.AD_count['label']==1)]['trans_rate'])self.RD.append(rd_value)print("渠道{0}相对于渠道{1}的风险差异RD为:{2}".format(chn1,chn2,self.RD[-1]))#计算ORdef _OR_cul(self):self.OR = []for chn1, chn2 in self.channel_comb:numerator = float(self.AD_count[(self.AD_count['channel']==chn1)&(self.AD_count['label']==1)]['user_count'])/float(self.AD_count[(self.AD_count['channel']==chn2)&(self.AD_count['label']==1)]['user_count'])denominator = float(self.AD_count[(self.AD_count['channel']==chn1)&(self.AD_count['label']==0)]['user_count'])/float(self.AD_count[(self.AD_count['channel']==chn2)&(self.AD_count['label']==0)]['user_count'])or_value = numerator/denominatorself.OR.append(or_value)print("渠道{0}相对于渠道{1}的几率OR为:{2}".format(chn1,chn2,self.OR[-1]))#计算APdef _AP_cul(self):self.AP = []for i in range(len(self.channel_comb)):chn1 = self.channel_comb[i][0]chn2 = self.channel_comb[i][1]ap_value = (self.OR[i]-1)/self.OR[i]self.AP.append(ap_value)print("渠道{0}相对于渠道{1}的归因分数AP为:{2}".format(chn1,chn2,self.AP[-1]))#计算PAFdef _PAF_cul(self):self.PAF = []for i in range(len(self.channel_comb)):chn1 = self.channel_comb[i][0]chn2 = self.channel_comb[i][1]pop = float(self.AD_count[(self.AD_count['channel']==chn1)&(self.AD_count['label']==1)]['total_count'])/self.AD_count['user_count'].sum()paf_value = (pop*(self.OR[i]-1))/(pop*(self.OR[i]-1)+1)self.PAF.append(paf_value)print("渠道{0}相对于渠道{1}的人口归因分数PAF为:{2}".format(chn1,chn2,self.PAF[-1]))#进行归因分析def attribution_analysis(self):self.AD_count = self.AD_data.groupby(['channel', 'label']).count().reset_index()self.AD_count.rename(columns={'user_id':'user_count'}, inplace = True)self.AD_count['total_count'] = self.AD_count.groupby("channel")["user_count"].transform('sum')self.AD_count['trans_rate'] = self.AD_count['user_count']/self.AD_count['total_count']print("各渠道用户转化和非转化用户量为:\n{}\n".format(self.AD_count))self.channel = np.unique(self.AD_count['channel'])#用于记录渠道对比组合self.channel_comb = []for chn1 in self.channel:for chn2 in self.channel:if chn1 != chn2:self.channel_comb.append([chn1, chn2])self._RR_cul()print("\n")self._RD_cul()print("\n")self._OR_cul()print("\n")self._AP_cul()print("\n")self._PAF_cul()if __name__ == "__main__":AD_data = pd.read_csv("D:/data/Attribution_test/AD_data.csv")attribution = Attribution_Analysis(AD_data['channel'], AD_data['label'], AD_data['user_id'])attribution.attribution_analysis()
程序运行结果如下:
不考虑计算精度,程序计算结果与上面例子手动计算结果是相等的。
可以看到。若以不暴露组为基准(可以是基础版本或以前版本),渠道A的转化效果明显比不暴露组好,在所有转化用户中,约有60%的用户是因为渠道A的展示发生了转化。若以渠道A为基准,不暴露组的效果比较差,在所有转化用户中,因为不暴露组的展示,转化用户丢失了69%(可以理解为,若都用渠道A进行展示,转化用户还会多69%?)