背景
业务异动归因时常见的一种的情况需要对大盘指标根据某个维度进行拆解,例如我们观测到大盘负反馈率上涨了,我们会想去拆分不同流量的负反馈率上涨对于大盘负反馈率上涨的贡献。
拆解思路
我们将每一种维度对于大盘指标的影响拆解为两个部分:指标上涨影响和结构变化影响
对于每个维度d:
d
维度指标上涨影响
=
d
维度基准期数量
对比期总量
∗
(
d
维度对比期指标值
−
d
维度基准期指标值
)
d维度指标上涨影响 = \frac{d维度基准期数量}{对比期总量} * (d维度对比期指标值 - d维度基准期指标值)
d维度指标上涨影响=对比期总量d维度基准期数量∗(d维度对比期指标值−d维度基准期指标值)
d
维度结构变化影响
=
d
维度对比期数量
−
d
维度基准期数量
对比期总量
∗
(
d
维度对比期指标值
−
基准期大盘指标值
)
d维度结构变化影响 = \frac{d维度对比期数量 - d维度基准期数量}{对比期总量} * (d维度对比期指标值 - 基准期大盘指标值)
d维度结构变化影响=对比期总量d维度对比期数量−d维度基准期数量∗(d维度对比期指标值−基准期大盘指标值)
原理解释
1、业务理解
指标变化就是在保持原本的量不变的情况下指标上涨的变化;
结构的变化可以理解为本来新增一个单位的数量应当是个平均人(也就是指标为基准期大盘均值),但是这个新增单位为维度d,所以对大盘的影响是这个单位在这个时期的指标值-大盘均值;
2、公式推导
这样的计算将会是一个messi的计算,所有的指标变化影响和结构变化影响求和会绝对等于大盘指标的指标的变化。
推导公式如下
- 整体的数量 D D D等于各个维度的数量 d i d_i di之和,即 D = ∑ i n d i D = \sum_i^n d_i D=∑indi
- 整体数量的变动 Δ D \Delta D ΔD 等于各个维度的数量变化 Δ d i \Delta d_i Δdi之和,即 Δ D = ∑ i n Δ d i \Delta D = \sum_i^n \Delta d_i ΔD=∑inΔdi
- 每个维度在基准期的指标值为 v i v_i vi ,基准期大盘均值为 V = ∑ i n d i v i D V =\frac{\sum_i^n d_iv_i}{D} V=D∑indivi
- 大盘指标变动
代码实现
数据格式
时间 | 维度1 | 维度2 | 数量 | 指标值 |
---|---|---|---|---|
基准期 | 性别 | 年龄 | dau | 均时长 |
对比期 | 性别 | 年龄 | dau | 均时长 |
def metric_decomposition(df,dimension_cols,num_col,metric_col,time_col,time_list):
'''
Args:
df (pd.DataFrame): the data source
dimension_cols (list): dimensions columns
num_cols (string):
metric_col (string):
time_col (string):
time_list (list): the values of time
Return:
pandas.DataFrame
'''
t0 = time_list[0]
t1 = time_list[1]
res = df.pivot_table(columns=time_col,index=dimension_cols,values=[num_col,metric_col],aggfunc=sum,dropna=False)
metric_t0 = (res[(metric_col,t0)]*res[(num_col,t1)]).sum()/res[(num_col,t0)].sum()
res[(num_col,'diff')] = res[(num_col,t1)] - res[(num_col,t0)]
res[(metric_col,'diff')] = res[(metric_col,t1)] - res[(metric_col,t0)]
res[(metric_col,'contribution')] = res[(metric_col,'diff')]*res[(num_col,t0)]
res[(num_col,'contribution')] = res[(num_col,'diff')]*(res[(metric_col,t1)] - metric_t0)
colsNeed = []
for i in [num_col,metric_col]:
for j in [t0,t1,'diff','contribution']:
colsNeed.append((i,j))
res = res[colsNeed]
res[('contribution','contribution')] = res[(num_col,'contribution')] + res[(metric_col,'contribution')]
return res