美文网首页
消费金融案例

消费金融案例

作者: SongSir1 | 来源:发表于2020-09-23 10:57 被阅读0次

    案例目录:

    一、单变量分析——用户首逾率增高问题
    二、用户群组分析——对相同生命周期阶段的用户进行垂直分析
    三、用户行为路径漏斗转化分析

    一. 单变量分析——用户首逾率增高

    单变量分析:

    • 单变量分析的目的是,通过对数据的整理、加工、组织和展示,并计算反应数据的集中趋势和离散程度的指标,对变量分布的特征和规律进行刻画和描述。不同类型的变量需要使用不同的方法和指标。
    • 单变量分析又称“单变量统计分析”,就是在一个时间点上对某一变量所进行的描述和统计,因而又可以分为单变量描述统计和单变量推论统计两种方式。

    1.案例背景

    日常监控数据时,发现某款消费贷产品首逾率有逐渐升高趋势,需要把首逾率降下来减少产品带来的损失。


    2.分析目标

    在客户申请时用来判断客户是否会逾期的条件,通过数据探查分析制定出可以有效降低首逾率的策略。

    3.分析思路

    在客户申请时,还原客户各个维度的数据,用单变量分析法从各个维度进行分析,找到区分好坏客户的变量,制定策略。

    3.1 数据观察处理

    • 对字段进行更名处理


    3.2 总体逾期率情况

    dt['是否逾期(1是,0否)'].sum()/dt.shape[0]
    
    [out]:0.307584667705824
    
    • 总体预期率达到30%,属于非常高的情况,下面需要使用单变量分析法,从各个维度单独分析,查看对预期的影响。

    3.3 筛选有效变量

    3.3.1 征信查询次数影响

    首先对客户的征信查询次数字段进行分组,统计每个分组区间的逾期人数。

    #征信查询次数分组
    def judge_zhengxin(x):
        try:
            x = int(x)
            if 0 <= x and x < 3:
                return '1:[0,3)'
            elif 3 <= x and x < 6:
                return '2:[3,6)'
            elif 6 <= x and x < 12:
                return '3:[6,12)'
            elif 12 <= x and x < 21:
                return '4:[12,21)'
            elif 21 <= x:
                return '5:[21,∞)'
        # 如果 x 不为int类型,则返回错误,即输出"缺失"
        except Exception as e:
            return '6:缺失'
    # 对征信查询次数字段进行分组
    dt['征信分组'] = dt['近半年征信查询次数'].apply(lambda x: judge_zhengxin(x))
    # 聚合统计
    dt_info_zhengxin = dt.groupby('征信分组').agg({'用户id':'count','是否逾期(1是,0否)':'sum'}).reset_index().rename(columns = {'用户id':"区间客户数","是否逾期(1是,0否)":"逾期人数"})
    dt_info_zhengxin
    

    接下来计算区间用户占比、首逾率情况:

    dt_info_zhengxin['区间用户占比'] = dt_info_zhengxin['区间客户数'].div(dt_info_zhengxin['区间客户数'].sum())
    dt_info_zhengxin['首逾率'] = dt_info_zhengxin['逾期人数'] / dt_info_zhengxin['区间客户数']
    # 绘图展示
    plt.figure(figsize = (15,6))
    plt.rcParams["font.size"] = 15
    
    plt.subplot(121)
    dt_info_zhengxin["区间客户数"].plot(kind = "pie",autopct='%.2f%%')
    plt.legend(dt_info_zhengxin["征信分组"],loc = 3, fontsize = 11)
    
    plt.subplot(122)
    plt.title("首逾率")
    dt_info_zhengxin["首逾率"].plot(kind = "bar")
    plt.xticks(range(6),dt_info_zhengxin["征信分组"],rotation =0)
    
    plt.tight_layout(pad = 2)
    plt.show()
    
    • 大部分客户查询次数均在12次以下,其中0-3,3-6,6-12次区间人数相差不大;
    • 首逾率基本跟随征信查询次数增长而增长,查询次数越大,首逾率越高,其中查询21+人次的总体首逾率达到了惊人的60%左右;
    • 可以初步判断征信查询次数与首逾率是呈正相关的。
    3.3.2 信用评级影响

    将信用评级划分为5个分组,并进行聚合统计

    def judge_pingji(x):
        if x =='A':
            return 'A'
        elif x == 'AA':
            return 'AA'
        elif x in ['B','C','D']:
            return 'BCD'
        elif x in ['E','HR','NC']:
            return 'ERC'
        else:
            return '缺失'
    # 分组
    dt['信用评级分组'] = dt['信用评级'].apply(lambda x:judge_pingji(x))
    dt_info_pingji = dt.groupby('信用评级分组').agg({'用户id':'count','是否逾期(1是,0否)':'sum'}).reset_index().rename(columns = {'用户id':"区间客户数",'是否逾期(1是,0否)':'逾期人数'})
    dt_info_pingji['区间客户占比'] = dt_info_pingji['区间客户数']/dt_info_pingji['区间客户数'].sum()
    dt_info_pingji['首逾率'] = dt_info_pingji['逾期人数']/dt_info_pingji['区间客户数']
    
    #绘图
    plt.figure(figsize = (15,6))
    plt.rcParams["font.size"] = 15
    
    plt.subplot(121)
    dt_info_pingji["区间客户数"].plot(kind = "pie",autopct='%.2f%%')
    plt.legend(dt_info_pingji["信用评级分组"],loc = 3, fontsize = 13)
    
    plt.subplot(122)
    plt.title("首逾率")
    dt_info_pingji["首逾率"].plot(kind = "bar")
    plt.xticks(range(5),dt_info_pingji["信用评级分组"],rotation =0)
    
    plt.tight_layout(pad = 2)
    
    • 除开缺失字段客户数,客户占比最高为评级BCD的用户,其次ERC,整体用户评级都比较低;
    • ERC评级用户首逾率最高达到52%左右,其次为BCD评级用户首逾率在36%;
    3.3.3 年龄影响

    先对年龄进行分组,并聚合统计分析

    bins = [0,25,30,35,40,45,100]
    labels = ["25岁及以下","26-30","31-35","36-40","41-45","45+"]
    dt["年龄分组"] = pd.cut(dt["年龄"],bins = bins, labels = labels)
    
    dt_info_age = dt.groupby("年龄分组").agg({"用户id":"count","是否逾期(1是,0否)":"sum"}).rename(columns={"用户id":"区间客户数","是否逾期(1是,0否)":"逾期人数"}).reset_index()
    dt_info_age["区间客户占比"] = dt_info_age["区间客户数"]/dt_info_age["区间客户数"].sum(0)
    dt_info_age["首逾率"] = dt_info_age["逾期人数"] / dt_info_age["区间客户数"]
    
    plt.figure(figsize = (15,6))
    plt.rcParams["font.size"] = 15
    
    plt.subplot(121)
    dt_info_age["区间客户数"].plot(kind = "pie",autopct='%.2f%%')
    plt.legend(dt_info_age["年龄分组"],loc = 3, fontsize = 13)
    
    plt.subplot(122)
    plt.title("首逾率")
    dt_info_age["首逾率"].plot(kind = "bar")
    plt.xticks(range(5),dt_info_age["年龄分组"],rotation =0)
    
    plt.tight_layout(pad = 2)
    plt.show()
    
    • 客户中25岁及以下相对较多,其余人数占比均差不多
    • 首逾率情况都在30%左右,较为均衡
    • 初步判断首逾率与年龄关系不大

    3.4 计算提升度

    在进行变量分析之后,这时我们就要从中筛选中较为有效的变量了,这里涉及到一个衡量变量是否有效的指标,提升度。

    提升度:通俗的来说就是衡量拒绝最坏那一部分的客户之后,对整体的风险控制的提升效果。 提升度越高,说明该变量可以更有效的区分好坏客户,能够更少的误拒好客户。
    计算公式:提升度 = 最坏分箱的首逾客户占总首逾客户的比例 /该分箱的区间客户数占比
    例如:上表中征信总查询次数中,最坏分箱为4:[21,∞),首逾客户为1923,总逾期客户为17365,该分箱区间客户数占比为5.69%,所以提升度就是(1923/17365)/5.69%=11%/5.69%=1.94。
    注意:
    提升度不是和逾期率成正比的,提升度说明的是这个变量下面有很大一部分人是会逾期的,它的大小是告诉我们这个变量有必要写到放贷策略里面去做优化,但是如果这部分人占整体的比例不高,那最终对逾期率影响也不大,但确实是能为企业减少风险。

    计算征信查询次数的提升度:(1.94)

    p1 = dt_info_zhengxin.iloc[dt_info_zhengxin['首逾率'].idxmax()]['逾期人数']/dt_info_zhengxin['逾期人数'].sum()
    p2 = dt_info_zhengxin.iloc[dt_info_zhengxin['首逾率'].idxmax()]['区间用户占比']
    up_rate1 = p1/p2
    up_rate1 
    
    # 提升度
    [out]:1.9458254325820934
    

    计算信用评级的提升度:(1.71)

    p1 = dt_info_pingji.iloc[dt_info_pingji['首逾率'].idxmax()]['逾期人数']/dt_info_pingji['逾期人数'].sum()
    p2 = dt_info_pingji.iloc[dt_info_pingji['首逾率'].idxmax()]['区间客户占比']
    up_rate2 = p1/p2
    up_rate2
    
    # 提升度
    [out]:1.7147127611157038
    

    计算年龄的提升度:(1.08)

    p1 = dt_info_age.iloc[dt_info_age["首逾率"].idxmax()]["逾期人数"]/dt_info_age["逾期人数"].sum()
    p2 = dt_info_age.iloc[dt_info_age["首逾率"].idxmax()]["区间客户占比"]
    up_rate3 = p1/p2
    up_rate3
    
    [out]:1.0786323478681992
    

    结果:征信查询次数提升度为1.94,信用评级提升度为1.71,年龄的提升度为1.08,选择征信查询次数的提升度。

    3.5 解决方案

    在以上过程中,我们根据计算得知提升度最高的征信查询次数,也就是说征信查询次数对于首逾率的影响最大。我们不妨将其最坏分箱的人全部拒绝,计算提出后的首逾率降幅为多少。

    new_yuqi_nums = dt_info_zhengxin["逾期人数"].sum() - dt_info_zhengxin.iloc[dt_info_zhengxin["首逾率"].idxmax()]["逾期人数"]
    new_yuqi_rate = new_yuqi_nums / (dt_info_zhengxin["区间客户数"].sum() - dt_info_zhengxin.iloc[dt_info_zhengxin["首逾率"].idxmax()]["区间客户数"])
    # 原始整体首逾率为:
    old_rate = dt['是否逾期(1是,0否)'].sum()/dt.shape[0]
    # 下降幅度
    diff = (dt['是否逾期(1是,0否)'].sum()/dt.shape[0])  -  new_yuqi_rate
    print("新的首逾率:",new_yuqi_rate)
    print("- "*20)
    print("原始的首逾率:",old_rate )
    print("- "*20)
    print("首逾率下降幅度:",diff )
    
    新的首逾率: 0.2900287361718911
    - - - - - - - - - - - - - - - - - - - - 
    原始的首逾率: 0.307584667705824
    - - - - - - - - - - - - - - - - - - - - 
    首逾率下降幅度: 0.017555931533932867
    
    • 通过对征信次数大于21次的用户拒绝后,首逾率为29%,下降了1.76%;
    • 虽然首逾率下降比例较少,但这部分的确能够起到影响作用。

    二、用户群组分析——对相同生命周期阶段的用户进行垂直分析

    群组分析:

    • 通过字面意思即可理解,群组分析法就是按某个特征对数据进行分组,通过分组比较,得出结论的方法。
    • 简单举例:将用户数据按性别特征,可以分组为男性和女性,将用户注册时间作为特征,按月份分组,可以分为1月,2月,3月进行环比比较,以及对他的留存率、活跃率、付费率等进行分析。

    群组分析的作用:
    1.对处于相同生命周期阶段的用户进行垂直分析,从而比较得出相似群体随时间的变化。
    2.通过比较不同的同期群,可以从总体上看到,应用的表现是否越来越好了。从而验证产品改进是否取得了效果。

    1.案例目的

    通过用户的订单消费情况,对比同一月份的新用户留存率的变化趋势,以及不同时间期的新用户在同周期时的留存率情况

    2.案例过程

    • 数据一共有7个字段

    orderid:订单编号
    orderdate:订单日期
    userid:用户编号
    totalcharges:消费金额
    因为在这里分析的是用户留存率情况,其他字段咱不需要

    2.1 数据处理

    需要从月份维度进行分析,先根据用户订单编号增加一个年月字段,再选择用户最小消费月份为首次消费时间

    # 增加年月字段
    df['orderperiod'] = df.orderdate.apply(lambda x:x.strftime("%Y-%m"))
    #增加最早消费时间
    # 根据索引对齐,需先将orderid设置为索引列
    df.set_index("userid",inplace = True)
    df["chortgroup"] = df.groupby("userid").agg({"orderperiod":"min"})
    df.reset_index(inplace = True)
    

    orderperiod:用户消费月份
    chortgroup:用户最早消费时间(出现的时间点)

    2.2 按用户按照最早消费时间分组并编号
    cohorts = df.groupby(['chortgroup','orderperiod',]).agg({'userid':pd.Series.nunique,'orderid':pd.Series.nunique,'totalcharges':'sum'})
    cohorts.rename(columns={"userid":"totalusers",
                           "orderid":"totalorders"},inplace=True)
    # 定义编号函数
    def cohorts_period(x):
        x['cohortperiod'] = np.arange(len(x)) + 1
        return x
    # 编号
    #cohorts.groupby('chortgroup') 后 每一个小群组分别是以orderperiod为index的群组
    cohorts = cohorts.groupby('chortgroup').apply(cohorts_period)
    cohorts = cohorts.reset_index().set_index(['chortgroup','cohortperiod'])
    cohorts
    
    • 上图中,已经按照用户首月时间对随后几个月的消费情况进行了统计
    • 但其中可能是数据缺失的原因,消费金额列出现为0的情况,但这并不影响我们对留存率的计算
    2.3 计算用户留存率

    每个月的首月用户数

    cohort_group_size = cohorts["totalusers"].groupby(level=0).first()
    
    chortgroup
    2009-01    20
    2009-02    28
    2009-03    12
    2009-04     8
    Name: totalusers, dtype: int64
    

    计算每月留存率

    cohorts_liucun = cohorts["totalusers"].unstack(0).div(cohort_group_size,axis = 1).fillna(0)
    cohorts_liucun
    

    绘图展示:
    # 绘图
    plt.rcParams["font.size"] = 14
    plt.rcParams["font.sans-serif"] = ["SimHei"]
    fig, ax = plt.subplots(1,figsize = (10,6),dpi = 80)
    ax.plot(cohorts_liucun)
    ax.set_xticks(range(1,13))
    ax.set_title('留存率')
    ax.grid(0.5)
    ax.legend(cohorts_liucun.columns)
    plt.show()
    
    # 热力图
    import seaborn as sns
    sns.set(style="white")
    
    plt.rcParams["font.size"] = 16
    plt.rcParams["font.sans-serif"] = ["SimHei"]
    plt.figure(figsize=(12,6))
    plt.title("用户留存率:热力图")
    sns.heatmap(cohorts_liucun.T,mask=cohorts_liucun.T.isnull(),annot=True,fmt=".0%")
    plt.show()
    

    3.总结

    • 整体用户留存率偏低,在5月就已经没有用户;
    • 其中3、4月份用户在3月已经消失,而1、2月用户生命周期相对较长,在5月才消失;
    • 预测可能1月、2月有活动,特别是1月份的,能够让用户的留存较高,对于此类情况的产生需要想办法增加用户留存,比如持续推出新品、给用户发短信、推出优惠活动等。

    三、用户行为路径漏斗转化分析

    用户行为路径分析:
    用户行为路径分析是一种监测用户流向,从而统计产品使用深度的分析方法。它主要根据每位用户在App或网站中的点击行为日志,分析用户在App或网站中各个模块的流转规律与特点,挖掘用户的访问或点击模式,进而实现一些特定的业务用途,如App核心模块的到达率提升、特定用户群体的主流路径提取与浏览特征刻画,App产品设计的优化与改版等。
    行为路径分析有如下作用:
    1.可视化用户流向,对海量用户的行为习惯形成宏观了解。
    2.定位影响转化的主次因素,使产品的优化与改进有的放矢。

    用户路径的分析转化结果通常以桑基图形式展现,以目标事件为起点/终点,详细查看后续/前置路径的流向,可以详细查看某个节点事件的转化情况。


    桑基图

    1.案例背景

    案例基于网络消费贷款形式,对消费贷借款进行复盘分析,增加用户借贷率。

    2.案例过程

    2.1 数据源观察

    每日访问信息 用户信息
    • data:日期
    • PV:访问量
    • UV:独立用户访问量(访问用户数)
    • rigist_cnt:注册数
    • regist_rate:访客注册率
    • active_cnt:激活数
    • new_cus:是否为新用户(1:是,0:否)
    • lending:是否放贷(1:是,0:否)

    2.2 计算新、老用户的放贷数和申请数

    新用户:

    dt_check_1 = dt_check.query("new_cus == 1")
    pt_1 = pd.pivot_table(data=dt_check_1,index='date',values='lending',aggfunc=[np.sum,'count'])
    pt_1.columns = pt_1.columns.droplevel(1)
    pt_1.columns = ['新用户放贷数','新用户申请数']
    pt_1['放贷率'] = pt_1['新用户放贷数'] / pt_1['新用户申请数']
    pt_1 = pt_1.reset_index()
    pt_1.head()
    # 平均放贷率
    pt_1["新用户放贷率"].mean()
    
    # 平均放贷率
    [out]:0.18942741473488545
    

    老用户:

    dt_check_0 = dt_check.query("new_cus == 0")
    pt_0 = pd.pivot_table(dt_check_0,index = 'date',values='lending',aggfunc=[np.sum,'count'])
    pt_0.columns = pt_0.columns.droplevel(1)
    pt_0.columns = ['老用户放贷数','老用户申请数']
    pt_0['放贷率'] = pt_0['老用户放贷数'] / pt_0['老用户申请数']
    pt_0.reset_index(inplace = True)
    pt_0.head()
    pt_0['放贷率'].mean()
    
    # 平均放贷率
    [out]:0.28226736226736227
    
    • 老用户的平均放贷率比新用户要高出许多,这也是对于老用户的信赖。

    2.3 计算复借率

    老用户定义:在这里,我们定义前一天借贷的新用户,第二天继续借款就为老用户
    先创建老用户人数列表,5.1-5.29的新用户为5.2-5.30日的老用户,再在首位随机插入一个数值表示5.1日的老用户

    old = list(pt_1['新用户放贷数'])[0:29] 
    old.insert(0,24) 
    

    将数据与老用户放贷率表按日期进行匹配,计算复借率(复借率 = 老用户申请数 / 老用户数)

    data = {'date':pt_1['date'],'老用户数':old}   
    dt_old = pd.DataFrame(data)
    pt_0_m = pd.merge(pt_0,dt_old,on='date')
    pt_0_m['老用户复借率'] = pt_0_m['老用户申请数'] / pt_0_m['老用户数']
    pt_0_m['老用户复借率'].mean()
    
    复借率走势
    # 平均复借率
    [out]:0.3471876898455787
    
    • 5月复借率走势跌宕起伏,最低不到10%,最高却超过90%,猜测在复借率较高的那几天可能有营销活动在促进借贷,
    • 整月平均复借率为34.7%左右

    2.4 计算各节点转换率并绘制漏斗图

    节点结算:
    计算当月每日PV、UV、注册数、活跃数、新用户申请数、新用户放贷数

    dt = pd.merge(pt_1,dt_flow,on='date',how='left')  #合并新客户
    dt_1 = pd.merge(dt,pt_0_m,on='date',how='left')   #合并老客户复借率
    # 汇总
    dt_sum = dt_1.drop('date',axis=1)
    dt_sum.loc['Row_sum'] = dt_sum.apply(lambda x:x.sum())
    # 提取需要的字段
    dt_desc = dt_sum[dt_sum.index == 'Row_sum'][['PV','UV','regist_cnt','active_cnt','新用户申请数','新用户放贷数']]
    dt_desc = dt_desc.T.reset_index()
    dt_desc.columns = ['指标','汇总']
    
    当月总体指标汇总
    绘制漏斗图:
    from plotly import graph_objects as go
    trace = go.Funnel(
        y = dt_desc['指标'],
        x = dt_desc['汇总'],
        # 表示图片展示内容样式  “value+percent previous”:数值+百分比 占前一层比例(可选)
        textinfo = 'value+percent previous',
        marker = dict(color=["deepskyblue", "lightsalmon", "tan", "teal", "silver", "yellow"]),  #颜色参数
        connector = {"line": {"color": "royalblue", "dash": "solid", "width": 2}})
    data = [trace]
    fig = go.Figure(data)
    fig.show()
    
    月度各指标漏斗图
    • 转换率在 UV → regist_cnt 即访问用户→注册用户这一步骤转换率很低,需要进行策划活动提高用户注册数,比如新用户注册送礼等;
    • 注册用户转为活跃用户,以及活跃用户转为申请用户指标均处于较高的水平,需要维持下去;
    • 放贷成功率比较低,可以优化算法模型,在保证资金安全的情况下提高放贷率。

    相关文章

      网友评论

          本文标题:消费金融案例

          本文链接:https://www.haomeiwen.com/subject/mgnwyktx.html