![df061969bbc16ed3025ef727b6daf46c.png](https://i-blog.csdnimg.cn/blog_migrate/6672f24dc6f0e783da71e355c9babf43.jpeg)
目录:
- 项目介绍
- 分析思路
- 分析流程
- 总结
一、项目介绍
本文是对消金公司监控报告中,发现某款消费贷产品首逾率有持续走高的趋势,对影响首逾率的因素进行分析并挖掘出导致首逾走高的因素,提出建议把首逾率降下来以减少产品带来的损失。
二、分析思路
因为我们所要分析的策略是将要在客户申请时用来判断客户是否会逾期的条件,所以策略分析时的基本思路就是还原这些有首逾表现的客户在申请时的数据(这个还原是指提取出客户在申请时点各个维度的数据,越多越好) ,然后利用这些数据去找出能够区分好坏客户的变量,制定策略。
三、分析流程
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](https://i-blog.csdnimg.cn/blog_migrate/ea3d05804e1aeb9f6ec610084ca87f14.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](https://i-blog.csdnimg.cn/blog_migrate/95bb81add5e9375bf5145c842531ba47.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](https://i-blog.csdnimg.cn/blog_migrate/272b521eaa2666a171b08606fe1ff6c5.png)
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info = dt.groupby("征信分组").agg({
"用户id":'count',
"是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
"是否逾期(1是,0否)":"区间逾期客户数"})
dt_info
![84a4951f4f2f21d3076ca902a4ca95e0.png](https://i-blog.csdnimg.cn/blog_migrate/4ea16a66f2393f02fc566aef021547c4.png)
dt_info['区间用户占比']=dt_info["区间客户数"]/dt_info["区间客户数"].sum()
dt_info
![5c42bdcf0335bd4159a76df6a0d945fe.png](https://i-blog.csdnimg.cn/blog_migrate/72080b5e344e0eeb5883c82973911e0f.png)
dt_info["区间没有逾期客户数"]=dt_info["区间客户数"]-dt_info["区间逾期客户数"]
dt_info
![3e211aa45407c4c81e392fd80071b24f.png](https://i-blog.csdnimg.cn/blog_migrate/623774503e13c5d91500c57ef8d794b8.png)
dt_info["区间首逾率"]=dt_info["区间逾期客户数"]/dt_info["区间客户数"]
dt_info
![9110b096069633c2f0a35219610e26ea.png](https://i-blog.csdnimg.cn/blog_migrate/8f6cc1f8735c0454d126c162d6cc3177.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](https://i-blog.csdnimg.cn/blog_migrate/8a75e8d30685db7eca419d7991cc6b1a.png)
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info2 = dt.groupby("信用评级分组").agg({
"用户id":'count',
"是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
"是否逾期(1是,0否)":"区间逾期客户数"})
dt_info2
![560e41bdc41a99393db1d473d6e8e344.png](https://i-blog.csdnimg.cn/blog_migrate/46b872f06205a137839e1a517dbdf908.png)
dt_info2['区间用户占比']=dt_info2["区间客户数"]/dt_info2["区间客户数"].sum()
dt_info2
![ba2dbd65be969823cfff9c3bb2859a98.png](https://i-blog.csdnimg.cn/blog_migrate/b66c0473c696273e732ed84effd75c1b.png)
dt_info2["区间没有逾期客户数"]=dt_info2["区间客户数"]-dt_info2["区间逾期客户数"]
dt_info2
![370636702829072d75ab905417cf69b6.png](https://i-blog.csdnimg.cn/blog_migrate/01f28286be91ce0b6cca2d36484b33c9.png)
dt_info2["区间首逾率"]=dt_info2["区间逾期客户数"]/dt_info2["区间客户数"]
dt_info2
![76e579c6e0790d9d180c2f21a8b985f2.png](https://i-blog.csdnimg.cn/blog_migrate/0af93136b3e133a40248e092a2c9c586.png)
# 征信次数分组的首逾率情况
dt_info
![01af3a5707cc3dd01676a0c8db61fe7e.png](https://i-blog.csdnimg.cn/blog_migrate/529af230bd8e06557aa3f4e81fb53533.png)
2.3 年龄分组
dt.head()
![f4dee2ccc6ea7d420dfc3498318686b0.png](https://i-blog.csdnimg.cn/blog_migrate/06eebfb83af3213084d4e6d18d03ca7c.jpeg)
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](https://i-blog.csdnimg.cn/blog_migrate/b9c4d8faab4255c35b0c761a3933baff.jpeg)
# 分组统计各个分组的情况
# 区间用户占比、未逾期客户数要另外计算
dt_info3 = dt.groupby("年龄分组").agg({
"用户id":'count',
"是否逾期(1是,0否)":sum
}).reset_index().rename(columns={"用户id":"区间客户数",
"是否逾期(1是,0否)":"区间逾期客户数"})
dt_info3
![edc88fb26cddafb866080a57881008fa.png](https://i-blog.csdnimg.cn/blog_migrate/fe3c2f6586390a89056f8fbaaf304647.png)
dt_info3['区间用户占比']=dt_info3["区间客户数"]/dt_info3["区间客户数"].sum()
dt_info3
![b5f97bc1b53ee57ca65dae030c552f14.png](https://i-blog.csdnimg.cn/blog_migrate/91523e13330309317e606b336ee95ea1.png)
dt_info3["区间没有逾期客户数"]=dt_info3["区间客户数"]-dt_info3["区间逾期客户数"]
dt_info3
![fcc452dc5946074ef814ee5405cd2ae6.png](https://i-blog.csdnimg.cn/blog_migrate/87b759ec5bf4f8bf8c9b5376592f6d38.png)
dt_info3["区间首逾率"]=dt_info3["区间逾期客户数"]/dt_info3["区间客户数"]
dt_info3
![602bd0da749dea8bf67eeea858d5680e.png](https://i-blog.csdnimg.cn/blog_migrate/55ed524b2e03c30ccf4edc82a861c364.png)
3、计算提升度
在进行变量分析之后,这时我们就要从中筛选较为有效的变量了,这里涉及到一个衡量变量是否有效的指标,提升度。
提升度:通俗的来说就是衡量拒绝最坏那一部分的客户之后,对整体的风险控制的提升效果。 提升度越高,说明该变量可以更有效的区分好坏客户,能够更少的误拒好客户。
计算公式:提升度=最坏分箱的首逾客户占总首逾客户的比例 /该分箱的区间客户数占比
- 例如:上表中征信总查询次数的最坏分箱提升度就是(1923/17365)/(3213/56456)=11%/5.69%=1.93 提升度这个指标一般来说都是用来一批变量分析里做相对比较,很多时候都是在有限的变量里尽可能选提升度更高的变量来做策略。
dt_info
![c767b7473d4cc0d6f9b7e9e64166435a.png](https://i-blog.csdnimg.cn/blog_migrate/9e215490ca9c5d734d51b0fccbb10be5.png)
dt_info["区间首逾率"]
![8ef15e6cac8f999750bf5e9f62b88d37.png](https://i-blog.csdnimg.cn/blog_migrate/f3d036e5ba8943a3f4901085a50a61d2.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](https://i-blog.csdnimg.cn/blog_migrate/80d857d217abaed5f501b46611587b4d.png)
dt_info2["区间首逾率"].idxmax()
3
dt_info2.iloc[dt_info2["区间首逾率"].idxmax()]
![b99b5ff6220c5aaf3df82492551a5bd9.png](https://i-blog.csdnimg.cn/blog_migrate/b3e918158ae605a496463ff441cde8d3.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](https://i-blog.csdnimg.cn/blog_migrate/e4e3446f9641fb746be184135a8cc386.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](https://i-blog.csdnimg.cn/blog_migrate/f0e644fc2f1e453590e98caac07555c0.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%