Python TGI实战分析(个人笔记)

关注微信公共号:小程在线

关注****博客:程志伟的博客

 

完整脚本在公共号

 

TGI:即Target Group Index(目标群体指数),可反映目标群体在特定研究范围(如地理区域、人口统计领域、媒体受众、产品消费者)内的强势或弱势。

TGI指数= [目标群体中具有某一特征的群体所占比例/总体中具有相同特征的群体所占比例]*标准数100。

例如:将某地区15-24岁的人作为目标群体,将去[电影网站A]看电影作为相同特征;若该地区15-24岁的人中,有8.9%的人去过[电影网站A]看电影,而在该地区总体人群中,有6.6%的人去过[电影网站A]看电影,则[电影网站A]在15-24岁人群中的TGI指数是134.9(8.9%/6.6%×100),其数额越大,就表明目标群体吻合度就越强势。

TGI指数表征不同特征用户关注问题的差异情况,其中TGI指数等于100表示平均水平,高于100,代表该类用户对某类问题的关注程度高于整体水平。

 

 

目标:哪些城市的人有高客单偏好

• 特征,高客单,即客户单次购买超过 50 元
• 目标群体,就是各个城市,这里我们可以分别计算出所有城市客户的高客单偏好
• 至于总体,就非常直白了,计算所涉及到的所有客户即为总体
解题的关键在于,计算出不同城市,高客单人数及所占的比例。

 

加载包并读取数据集

import pandas as pd
df = pd.read_excel(r'F:\Python\案例数据.xlsx')
df.head()
Out[1]: 
           品牌名称    买家昵称                付款日期  订单状态   实付金额  邮费   省份   城市  购买数量
0  viva la vida    做快淘饭 2019-04-18 00:03:00  交易成功  22.32   0   北京  北京市     1
1  viva la vida   作自有世祟 2019-02-17 00:03:51  交易成功  87.00   0   上海  上海市     1
2  viva la vida    作雪白室 2019-04-18 00:01:43  交易成功  97.66   0  福建省  福州市     2
3  viva la vida  作美女购物主 2019-01-11 23:35:01  交易成功  37.23   0  河南省  安阳市     3
4  viva la vida  作美女购物主 2019-02-18 14:16:03  交易成功  29.50   0  河南省  安阳市     2

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 28832 entries, 0 to 28831
Data columns (total 9 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   品牌名称    28832 non-null  object        
 1   买家昵称    28832 non-null  object        
 2   付款日期    28832 non-null  datetime64[ns]
 3   订单状态    28832 non-null  object        
 4   实付金额    28832 non-null  float64       
 5   邮费      28832 non-null  int64         
 6   省份      28832 non-null  object        
 7   城市      28832 non-null  object        
 8   购买数量    28832 non-null  int64         
dtypes: datetime64[ns](1), float64(1), int64(2), object(5)
memory usage: 2.0+ MB

Python TGI实战分析(个人笔记)

单个用户打标
第一步,我们先判断每个用户是否属于高客单的人群,所以先按用户昵称进行分组,看每位用户的平均支付金额。这里用平均,是因为有的客户多次购买, 而每次下单金额也不一样,故平均之。

gp_user = df.groupby('买家昵称')['实付金额'].mean().reset_index()
gp_user.head()
Out[3]: 
         买家昵称    实付金额
0   .blue_ram  49.450
1  .christiny  22.000
2     .willn1  34.570
3        .托托m  37.475
4       0000妮  13.500

Python TGI实战分析(个人笔记)

 

定义一个判断函数,如果单个用户平均支付金额大于 50,就打上“高客单”的类别,否则为低客单,再用 apply 函数调用:
def if_high(x):
    if x > 50:
        return '高客单'
    else:
        return '低客单'

gp_user['客单类别'] = gp_user['实付金额'].apply(if_high)
gp_user.head(10)
Out[4]: 
          买家昵称    实付金额 客单类别
0    .blue_ram  49.450  低客单
1   .christiny  22.000  低客单
2      .willn1  34.570  低客单
3         .托托m  37.475  低客单
4        0000妮  13.500  低客单
5     0009797王  94.500  高客单
6      000xyx0  99.250  高客单
7    000米粒儿米粒0  24.500  低客单
8  00556旭79618  23.860  低客单
9        00不哭0  53.545  高客单

 

匹配城市
单个用户的金额和客单标签已经搞定,下一步就是补充每个用户的地域字段,一句pd.merge 函数就能搞定。由于源数据是未去重的,我们得先按昵称去重,不然匹配的结果会有许多重复的数据:

df_dup = df.loc[df.duplicated('买家昵称') == False, :]

df_merge = pd.merge(gp_user, df_dup, left_on='买家昵称', right_on='买家昵称', how='left')
df_merge.head()
Out[6]: 
         买家昵称  实付金额_x 客单类别          品牌名称  ... 邮费   省份   城市  购买数量
0   .blue_ram  49.450  低客单  viva la vida  ...  0   上海  上海市     1
1  .christiny  22.000  低客单  viva la vida  ...  0  江苏省  南京市     1
2     .willn1  34.570  低客单  viva la vida  ...  0  山东省  烟台市     2
3        .托托m  37.475  低客单  viva la vida  ...  0   上海  上海市     3
4       0000妮  13.500  低客单  viva la vida  ...  0  广东省  揭阳市     1

[5 rows x 11 columns]

 

高客单 TGI 指数计算
要计算每个城市高客单 TGI 指数,需要得到每个城市高客单、低客单的人数分别是多少。

df_merge = df_merge[['买家昵称', '客单类别', '省份', '城市']]

result = pd.pivot_table(
    df_merge,
    index = ['省份', '城市'],
    columns = '客单类别',
    aggfunc = 'count',
)
result.head()
Out[8]: 
               买家昵称        
客单类别            低客单     高客单
省份  城市                     
上海  上海市      2818.0  2374.0
云南省 临沧市         3.0     2.0
    丽江市         1.0     3.0
    保山市         6.0     2.0
    大理白族自治州     9.0     8.0

 

这样得到的结果包含了层次化索引,要得到“高客单”列,需要先索引“买家昵称”,再索引“高客单”:

result['买家昵称']['高客单'].reset_index().head()
Out[9]: 
    省份       城市     高客单
0   上海      上海市  2374.0
1  云南省      临沧市     2.0
2  云南省      丽江市     3.0
3  云南省      保山市     2.0
4  云南省  大理白族自治州     8.0

 

拿到了每个省市的高客单人数,然后再拿到低客单的人数,进行横向合并:
tgi = pd.merge(
    result['买家昵称']['高客单'].reset_index(),
    result['买家昵称']['低客单'].reset_index(),
    left_on = ['省份', '城市'],
    right_on = ['省份', '城市'],
    how = 'inner'
)
tgi.head()
Out[10]: 
    省份       城市     高客单     低客单
0   上海      上海市  2374.0  2818.0
1  云南省      临沧市     2.0     3.0
2  云南省      丽江市     3.0     1.0
3  云南省      保山市     2.0     6.0
4  云南省  大理白族自治州     8.0     9.0

 

目标群体中具有某一特征的群体所占比例:

我们再看看每个城市总人数以及高客单人数占比,来完成“目标群体中具有某一特征的群体所占比例”这个分子的计算:

tgi['总人数'] = tgi['高客单'] + tgi['低客单']
tgi['高客单占比'] = tgi['高客单'] / tgi['总人数']

tgi.head()

Python TGI实战分析(个人笔记)

 

有些非常小众的城市,高客单或者低客单人数等于 1 甚至没有,而这些值尤其是空值会影响结果的计算,我们要提前检核数据:
tgi.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 346 entries, 0 to 345
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   省份      346 non-null    object 
 1   城市      346 non-null    object 
 2   高客单     332 non-null    float64
 3   低客单     329 non-null    float64
 4   总人数     315 non-null    float64
 5   高客单占比   315 non-null    float64
dtypes: float64(4), object(2)
memory usage: 18.9+ KB

 

果然,高客单和低客单都有空值(可以理解为 0),从而导致总人数也存在空值,而 TGI 指数对于空值来说意义不大,所以我们剔除掉存在空值的行:

tgi = tgi.dropna()

 

总体中具有相同特征的群体所占比例:

接着统计总人数中,高客单人群的比例,来对标公式中的分母“总体中具有相同特征的群体所占比例”:

total_percentage = tgi['高客单'].sum() / tgi['总人数'].sum()
total_percentage
Out[14]: 0.41528303343887557

Python TGI实战分析(个人笔记)

 

TGI 指数:

最后一步,就是 TGI 指数的计算,并排序:
tgi['高客单TGI指数'] = tgi['高客单占比'] / total_percentage * 100
tgi = tgi.sort_values('高客单TGI指数', ascending=False)
tgi.head()

Python TGI实战分析(个人笔记)

发现了一个严重的问题: 高客单 TGI 指数排名靠前的城市,总客户数几乎不超过 10 人,这样的高客单人口占比,完全没有说服力。TGI 指数能够显示偏好的强弱,但很容易让人忽略具体的样本量大小, 这个是需要格外注意的。
对总人数进行筛选,用总人数的平均值作为阈值,只保留总人数大于平均值的城市:

tgi.loc[tgi['总人数'] > tgi['总人数'].mean(), :].head()Python TGI实战分析(个人笔记)