渠道归因(一)传统渠道归因

渠道归因(一)传统渠道归因

小P:小H,我又来了。。。最近在做ROI数据,但是有个问题。。。

小H:什么问题,不就是收入/成本吗?

小P:是的,每个渠道的成本很容易计算,但是收入就有点问题了。

小H:是不是不知道怎么分配啊?

小P:不愧是你,对的,用户在付费前经历过很多渠道,我感觉把收入分给谁都不好说

小H:这个也不复杂,关于渠道归因的方式有很多种,比如传统渠道归因、基于马尔可夫链、基于shapley value甚至是基于Attention-RNN深度学习。

说到渠道归因,那最容易想到的就是传统的渠道归因,这种方法一般是基于业务决策的。

首次归因:首次点击渠道赋予全部转化

末次归因:末次点击渠道赋予全部转化

线性(平均)归因:每个渠道均分转化

位置归因:自定义位置的权重,一般首位占50%,其余为0

时间衰减归因:距离转化的时间越短的渠道,可以获得越多的功劳权重,权重自定义

首次/末次/线性归因

# pip install Cython
# pip install ChannelAttribution
import pandas as pd
from ChannelAttribution import *
Looking for attribution at path level? Try markov_model_local_api() or ask for ChannelAttributionPro at [email protected]! Visit https://channelattribution.io for more information.
Version: 2.1.3

本文所有数据如果有需要的同学可关注公众号HsuHeinrich,回复【数据挖掘-渠道归因】自动获取~

Data = pd.read_csv('./Markov/Data.csv',sep=";")
Data.head() 

数据格式要求:

path:转化路径,以>连接

total_conversions:累计转化次数

total_conversion_value:累计转化收益

total_null:累计未转化次数

path total_conversions total_conversion_value total_null
0 eta > iota > alpha > eta 1 0.244 3
1 iota > iota > iota > iota 2 3.195 6
2 alpha > iota > alpha > alpha > alpha > iota > ... 2 6.754 6
3 beta > eta 1 2.402 3
4 iota > eta > theta > lambda > lambda > theta >... 0 0.000 2
# 传统启发式算法计算各渠道转化次数和转化收益
# first_touch:首次点击模型;last_touch:末尾点击模型;linear_touch:线性(平均)点击模型
heuristic_models(Data,"path","total_conversions", var_value='total_conversion_value')

渠道归因(一)传统渠道归因_第1张图片

位置归因

# 自定义位置归因函数,设置首尾权重各50%
def posAttribution(df, path, conversions):
    '''
    df:数据集
    path:用户旅程路径
    conversions:成功转化次数
    '''
    df=df.copy()
    df['leng']=df[path].map(lambda x: len(x.split(">")))
    df['first_touch']=df[path].map(lambda x: [x.strip() for x in x.split(">")][0])
    df['last_touch']=df[path].map(lambda x: [x.strip() for x in x.split(">")][-1])

    df['first_touch_conversions']=df[['leng',conversions]].apply(
        lambda x: x[conversions]*1 if x['leng']==1 else x[conversions]*0.5, axis=1)
    df['last_touch_conversions']=df[['leng',conversions]].apply(
        lambda x: 0 if x['leng']==1 else x[conversions]*0.5, axis=1)

    df1=df.groupby(['first_touch'])['first_touch_conversions'].sum()
    df2=df.groupby(['last_touch'])['last_touch_conversions'].sum()
    df_f=pd.merge(df1, df2, left_index=True, right_index=True, how = 'outer').reset_index()
    df_f['first_last_touch_conversions']=df_f['first_touch_conversions']+df_f['last_touch_conversions']
    df_f.drop(['first_touch_conversions','last_touch_conversions'], axis=1, inplace=True)
    
    return df_f
# 位置归因(首尾归因)
posAttribution(Data,"path","total_conversions")
first_touch first_last_touch_conversions
0 alpha 7377.5
1 beta 1910.0
2 delta 3.0
3 epsilon 315.0
4 eta 3665.5
5 gamma 128.5
6 iota 3980.5
7 kappa 152.0
8 lambda 1054.5
9 mi 2.0
10 theta 1129.5
11 zeta 67.0

时间衰减归因

from sklearn.preprocessing import StandardScaler, MinMaxScaler 
from pandas.api.types import is_string_dtype, is_numeric_dtype
import warnings
import pandas as pd
# 读取数据 数据为自定义的
df=pd.read_excel('datas.xlsx')
df.head()

渠道归因(一)传统渠道归因_第2张图片

# 自定义时间衰减归因 衰减权重为半衰。例如1->2,则1的权重是66.6%;1->2->3,则1的权重是50%,2的权重是33.3%
def lapsAttribution(df, path, conversions, last_time_lapse):
    def scum(l):
        s=0
        for i in range(1, len(l)+1):
            s+=i
        return s
    
    def lw(l):
        lw=[]
        n=scum(l)
        for i in range(1, len(l)+1):
            lw.append(1/n*i)
        return lw

    df['last_time_sp']=df[last_time_lapse].map(lambda x: str(x).split('>'))
    df['path_sp']=df[path].map(lambda x: [x.strip() for x in x.split(">")])
    df['lts_w']=df['last_time_sp'].map(lambda x:lw(x))
    df['conversions_sp']=df[[conversions,'lts_w']].apply(
            lambda x: [i*x[conversions] for i in x['lts_w']], axis=1)
    
    laps_touch=[]
    conversions_all=[]
    for i in df[['path_sp', 'conversions_sp']].values:
        for m in zip(i[0],i[1]):
            laps_touch.append(m[0])
            conversions_all.append(m[1])

    df_temp=pd.DataFrame({'laps_touch':laps_touch, 'laps_touch_conversions':conversions_all})
    df_f=df_temp.groupby(['laps_touch'])['laps_touch_conversions'].sum().reset_index()
    
    return df_f
lapsAttribution(df, 'path', 'total_conversions', 'last_time_lapse')
laps_touch laps_touch_conversions
0 alpha 0.300000
1 beta 1.333333
2 eta 2.833333
3 iota 13.033333
4 kappa 0.500000

总结

传统渠道归因还是需要依据业务决定的,只要你能说服业务按照其中一种方式进行收入分配,那到这一步基本就够了。实际上,传统的渠道归因是易于理解、好操作、结果接受程度高的~

共勉~

你可能感兴趣的:(数据分析,python,数据分析)