风控变量加工硬编码写sql_单变量分析-首逾率走高分析

df061969bbc16ed3025ef727b6daf46c.png

目录:

  • 项目介绍
  • 分析思路
  • 分析流程
  • 总结

一、项目介绍

本文是对消金公司监控报告中,发现某款消费贷产品首逾率有持续走高的趋势,对影响首逾率的因素进行分析并挖掘出导致首逾走高的因素,提出建议把首逾率降下来以减少产品带来的损失。

二、分析思路

因为我们所要分析的策略是将要在客户申请时用来判断客户是否会逾期的条件,所以策略分析时的基本思路就是还原这些有首逾表现的客户在申请时的数据(这个还原是指提取出客户在申请时点各个维度的数据,越多越好) ,然后利用这些数据去找出能够区分好坏客户的变量,制定策略。

三、分析流程

import pandas as pd
import numpy as np

import sqlalchemy


# 读取数据
engine = sqlalchemy.create_engine('mysql+pymysql://froghd:Froghd@123@localhost:3306/froghd')

sql_cmd = "select * from load_datas"

# 执行sql语句,获取数据
dt = pd.read_sql(sql=sql_cmd, con=engine)

dt.head()

d5e1354d06fc209c4f4b50bc05997889.png
#重命名
dt.rename(columns={
    "user_id":"用户id",
    "age":"年龄",
    "occupation":"职业",
    "work_times":"工作时间",
    "credit_score":"芝麻信用分",
    "credit_level":"信用评级",
    "credit_check_times":"近半年征信查询次数",
    "credit_card_use_rate":"信用卡额度使用率",
    "is_overdue":"是否逾期(1是,0否)"
},inplace=True)

dt.head()

787859e2901be7c0965c573c1a902e8d.png
dt.shape #56456条数据,9列

(56456, 9)

1、看一下这个产品总体的情况

#计算用户总数
dt['用户id'].count()  #也可以写作 dt.shape[0]

56456

#计算逾期客户数
dt["是否逾期(1是,0否)"].sum()

17365

# 计算总体首逾率 = 首逾客户数/总申请客户数
dt["是否逾期(1是,0否)"].sum()/dt['用户id'].count()

0.307584667705824

2、筛选出有效变量

这里用到单变量分析的方法,单变量分析的主要目的是筛选出好坏区分度较好的变量以便制定策略。在消金公司的日常工作中,会有专门负责爬取变量和计算加工变量数据的团队,他们在不断的去获取加工很多可能对风险控制有帮助的数据提供给我们风控团队,而我们风控人员就需要从这成千上万个变量中探查出能够控制逾期风险但同时又不会误拒很多好客户的变量。

拿到数据的第一步就是针对每个变量单独分析,查看其对逾期的影响。

2.1 征信查询次数分组

# 定义一个征信分组的函数
def judge_zhengxin(nums):
    try:
        nums = int(nums)
        if 0<=nums and nums<3:
            return '1:[0,3)'
        elif 3<=nums and nums<6:
            return '2:[3,6)'
        elif 6<=nums and nums<12:
            return '3:[6,12)'
        elif 12<=nums and nums<21:
            return '4:[12,21)'
        elif 21<=nums:
            return '5:[21,无穷)'
    except Exception as e:
        return "6:缺失"

# 新建一个字段记录分组信息
dt['征信分组']=dt['近半年征信查询次数'].apply(judge_zhengxin)

dt.head()

4d4b09169b83cb4517e3d764bfd20c6e.png
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info = dt.groupby("征信分组").agg({
    "用户id":'count',
    "是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
                                "是否逾期(1是,0否)":"区间逾期客户数"})
dt_info

84a4951f4f2f21d3076ca902a4ca95e0.png
dt_info['区间用户占比']=dt_info["区间客户数"]/dt_info["区间客户数"].sum()
dt_info

5c42bdcf0335bd4159a76df6a0d945fe.png
dt_info["区间没有逾期客户数"]=dt_info["区间客户数"]-dt_info["区间逾期客户数"]
dt_info

3e211aa45407c4c81e392fd80071b24f.png
dt_info["区间首逾率"]=dt_info["区间逾期客户数"]/dt_info["区间客户数"]
dt_info

9110b096069633c2f0a35219610e26ea.png

2.2 信用评级分组

# 定义一个征信分组的函数
def judge_pingji(level):
    if level=="A":
        return "A"
    elif level=="AA":
        return "AA"
    elif level in ("B","C","D"):
        return "BCD"
    elif level in ("E","HR","NC"):
        return "ERC"
    else:
        return "缺失"

# 新建一个字段记录分组信息
dt['信用评级分组']=dt['信用评级'].apply(judge_pingji)

dt.head()

730fed6ac90a52e027611e89c2263867.png
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info2 = dt.groupby("信用评级分组").agg({
    "用户id":'count',
    "是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
                                "是否逾期(1是,0否)":"区间逾期客户数"})
dt_info2

560e41bdc41a99393db1d473d6e8e344.png
dt_info2['区间用户占比']=dt_info2["区间客户数"]/dt_info2["区间客户数"].sum()
dt_info2

ba2dbd65be969823cfff9c3bb2859a98.png
dt_info2["区间没有逾期客户数"]=dt_info2["区间客户数"]-dt_info2["区间逾期客户数"]
dt_info2

370636702829072d75ab905417cf69b6.png
dt_info2["区间首逾率"]=dt_info2["区间逾期客户数"]/dt_info2["区间客户数"]
dt_info2

76e579c6e0790d9d180c2f21a8b985f2.png
# 征信次数分组的首逾率情况
dt_info

01af3a5707cc3dd01676a0c8db61fe7e.png

2.3 年龄分组

dt.head()

f4dee2ccc6ea7d420dfc3498318686b0.png
dt['年龄'].max()

50

dt['年龄'].min()

20

# 定义一个年龄分组的函数
def judge_nianling(age):
    try:
        nums = int(age)
        if 20<=age and age<30:
            return '1:[20,30)'
        elif 30<=age and age<40:
            return '2:[30,40)'
        elif 40<=age and age<50:
            return '3:[40,50)'
        elif 50<=age:
            return '4:[50,以上)'
    except Exception as e:
        return "6:缺失"

# 新建一个字段记录分组信息
dt['年龄分组']=dt['年龄'].apply(judge_nianling)

dt.head()

f49287687ce799085947118f9c92b79e.png
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info3 = dt.groupby("年龄分组").agg({
    "用户id":'count',
    "是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
                                "是否逾期(1是,0否)":"区间逾期客户数"})
dt_info3

edc88fb26cddafb866080a57881008fa.png
dt_info3['区间用户占比']=dt_info3["区间客户数"]/dt_info3["区间客户数"].sum()
dt_info3

b5f97bc1b53ee57ca65dae030c552f14.png
dt_info3["区间没有逾期客户数"]=dt_info3["区间客户数"]-dt_info3["区间逾期客户数"]
dt_info3

fcc452dc5946074ef814ee5405cd2ae6.png
dt_info3["区间首逾率"]=dt_info3["区间逾期客户数"]/dt_info3["区间客户数"]
dt_info3

602bd0da749dea8bf67eeea858d5680e.png

3、计算提升度

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

提升度:通俗的来说就是衡量拒绝最坏那一部分的客户之后,对整体的风险控制的提升效果。 提升度越高,说明该变量可以更有效的区分好坏客户,能够更少的误拒好客户。

计算公式:提升度=最坏分箱的首逾客户占总首逾客户的比例 /该分箱的区间客户数占比

  • 例如:上表中征信总查询次数的最坏分箱提升度就是(1923/17365)/(3213/56456)=11%/5.69%=1.93 提升度这个指标一般来说都是用来一批变量分析里做相对比较,很多时候都是在有限的变量里尽可能选提升度更高的变量来做策略。
dt_info

c767b7473d4cc0d6f9b7e9e64166435a.png
dt_info["区间首逾率"]

8ef15e6cac8f999750bf5e9f62b88d37.png
#求出区间首逾率最高的id
dt_info["区间首逾率"].idxmax()

4

#求出区间首逾率最高的id 对应的区间逾期客户数
dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间逾期客户数"]

1923

# 区间逾期客户数求和
dt_info["区间逾期客户数"].sum()

17365

#计算 最坏分箱的首逾客户占总首逾客户的比例
bad_rate = dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间逾期客户数"]/dt_info["区间逾期客户数"].sum()
bad_rate

0.11073999424128995

dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间客户数"]

3213

dt_info["区间客户数"].sum()

56456

#计算 该分箱的区间客户数占比
num_rate = dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间客户数"]/dt_info["区间客户数"].sum()
num_rate

0.056911577157432336

#征信总查询次数的最坏分箱提升度
bad_rate/num_rate

1.9458254325820934

# 计算各个指标的提升度
# 提升度=最坏分箱的首逾客户占总首逾客户的比例 /该分箱的区间客户数占比
# 这里最坏分箱就是根据征信分组后,首逾率最高的一组
# 获取最大值所在行,argmax 也可以,但是会有警告
dt_info["区间首逾率"].idxmax()
# dt_info.iloc[dt_info["区间首逾率"].idxmax()]
bad_rate = dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间逾期客户数"]/dt_info["区间逾期客户数"].sum()
num_rate = dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间客户数"]/dt_info["区间客户数"].sum()
bad_rate/num_rate

1.9458254325820934

dt_info2

a1cfa722766c4e78d3385543192c1dea.png
dt_info2["区间首逾率"].idxmax()

3

dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]

b99b5ff6220c5aaf3df82492551a5bd9.png
dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]

4251

dt_info2["区间逾期客户数"].sum()

17365

#计算 最坏分箱的首逾客户占总首逾客户的比例
bad_rate2 = dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]/dt_info2["区间逾期客户数"].sum()
bad_rate

0.11073999424128995

dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间客户数"]

8060

dt_info2["区间客户数"].sum()

56456

#计算 该分箱的区间客户数占比
num_rate2 = dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间客户数"]/dt_info2["区间客户数"].sum()
num_rate2

0.14276604789570638

#信用评级的最坏分箱提升度
bad_rate2/num_rate2

1.7147127611157038

# 信用评级的提升度
# dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]
bad_rate2 = dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]/dt_info2["区间逾期客户数"].sum()
num_rate2 = dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间客户数"]/dt_info2["区间客户数"].sum()
bad_rate2/num_rate2

1.7147127611157038

通过对所有变量的提升度进行倒序排列,发现个人征信总查询次数和客户信用评级的提升度最高,达到1.95和1.71

4、制定策略

通过上一步的单变量分析,我们筛出了’征信查询次数’、‘信用评级’这两个提升度最高的变量。现在我们看一下如果将这两个变量的最坏分箱的客户都拒绝之后,对整体逾期的影响。 这个影响就是指假设我们将‘征信总查询次数>=21的3213位客户全部拒绝’之后,剩下的客户逾期率相比拒绝之前的逾期率降幅是多少。

(1)征信查询次数的前后逾期差

dt_info

7dcca1ab297f1853ebe4fa8212e29e7b.png
dt_info["区间逾期客户数"].sum()

17365

dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间逾期客户数"]

1923

new_yuqi_nums = dt_info["区间逾期客户数"].sum() - dt_info.iloc[dt_info["区间首逾率"].idxmax()]["区间逾期客户数"]
new_yuqi_nums

15442

dt_info["区间客户数"].sum()

56456

new_yuqi_rate = new_yuqi_nums / dt_info["区间客户数"].sum()
new_yuqi_rate

0.27352274337537197

old_yuqi_nums = dt_info["区间逾期客户数"].sum()
old_yuqi_nums

17365

old_yuqi_rate = old_yuqi_nums / dt_info["区间客户数"].sum()
old_yuqi_rate

0.307584667705824

# 新的逾期率下降了 3.4%
old_yuqi_rate-new_yuqi_rate

0.03406192433045202

(2) 信用评级分组的前后逾期差

dt_info2

ca21282d789bc3a43274b21a179f611a.png
dt_info2["区间逾期客户数"].sum()

17365

dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]

4251

new_yuqi_nums = dt_info2["区间逾期客户数"].sum() - dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]
new_yuqi_nums

13114

dt_info2["区间客户数"].sum()

56456

new_yuqi_rate = new_yuqi_nums / dt_info2["区间客户数"].sum()
new_yuqi_rate

0.23228709083179822

old_yuqi_nums = dt_info2["区间逾期客户数"].sum()
old_yuqi_nums

17365

old_yuqi_rate = old_yuqi_nums / dt_info2["区间客户数"].sum()
old_yuqi_rate

0.307584667705824

# 即假设我们设置征信查询次数这个风控指标,并且把查询次数21次以上的都拒绝掉
# 然后来看首逾率是多少,有降低多少
# 逾期率 = 逾期人数 / 总人数
new_yuqi_nums = dt_info2["区间逾期客户数"].sum() - dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]["区间逾期客户数"]
new_yuqi_rate = new_yuqi_nums / dt_info2["区间客户数"].sum()

old_yuqi_nums = dt_info2["区间逾期客户数"].sum()
old_yuqi_rate = old_yuqi_nums / dt_info2["区间客户数"].sum()

new_yuqi_rate

0.23228709083179822

new_yuqi_rate

0.23228709083179822

old_yuqi_rate

0.307584667705824

# 新的逾期率下降了 7.52%
old_yuqi_rate-new_yuqi_rate

0.07529757687402577

四、总结

通过比较看出将信用评级分组为ERC的8060位客户全部拒绝之后,剩下的客户逾期率相比拒绝之前的逾期率降幅最高,下降了7.52%

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值