前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >信用卡“坏账”客户分析(一)

信用卡“坏账”客户分析(一)

作者头像
张俊红
发布2018-04-11 15:23:05
4.4K0
发布2018-04-11 15:23:05
举报
文章被收录于专栏:张俊红张俊红

总第92篇

01|背景:

随着人们的消费观念的升级,所谓的“花明天的钱,圆今天的梦”。银行以及私营企业推出了各种各样的消费金融服务,具有代表性的是各大银行的信用卡,支付宝的花呗、京东白条,还有一些专门针对针对学生群体的平台,比如趣分期哈、分期乐之类的,把这些统称为信用卡用户。

只要涉及到金融借贷的,就有可能有坏账的存在。

坏账说的通俗一点就是你借出去的钱要不回来了。

每个公司都在用各种手段来降低坏账的发生,最常见的方法就是根据一定的规则,给每个用户打分进行预测,哪些用户可能会发生坏账,针对预测结果采取相应的措施。

本篇将针对历史坏账用户进行分析,分析坏账用户都有哪些特征,为后续的建模做准备。数据来自kaggle上的https://www.kaggle.com/c/GiveMeSomeCredit/data 比赛。

02|导入数据:

代码语言:javascript
复制
#导入相关库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
#导入数据
df=pd.read_csv(r"D:\Data-Science\Exercisedata\评分卡\cs-training.csv",engine="python")
df.head(5)

因字段太长,所以预览不全,直接打印出columns。

代码语言:javascript
复制
print(df.columns)
----------------------------
Index(['ID', 'SeriousDlqin2yrs', 'RevolvingUtilizationOfUnsecuredLines', 'age',
       'NumberOfTime30-59DaysPastDueNotWorse', 'DebtRatio', 'MonthlyIncome',
       'NumberOfOpenCreditLinesAndLoans', 'NumberOfTimes90DaysLate',
       'NumberRealEstateLoansOrLines', 'NumberOfTime60-89DaysPastDueNotWorse',
       'NumberOfDependents'],
      dtype='object')
代码语言:javascript
复制
#数据指标解读
ID——用户编号
SeriousDlqin2yrs——好坏客户区分,这里以逾期90天为界,超过90天表示“坏客户”,用1表示是;未超过90天表示“好客户”,用0表示
RevolvingUtilizationOfUnsecuredLines——贷款以及信用卡可以用额度与总额度比值
age——借款人的年龄
NumberOfTime30-59DaysPastDueNotWorse——借款人逾期30-59天但过去两年不是坏账的次数(笔数)
DebtRatio——负债率,每月要支付的债务、赡养费、生活费占每月总收入的比值
MonthlyIncome——月收入
NumberOfOpenCreditLinesAndLoans——贷款和信用卡数量
NumberOfTimes90DaysLate——逾期90天的次数
NumberRealEstateLoansOrLines——固定资产贷款数量
NumberOfTime60-89DaysPastDueNotWorse——逾期60-89天次数
NumberOfDependents——家属数量

英文字段看着太难受了,利用df.rename()函数将columns转化为中文,

代码语言:javascript
复制
states={"ID":"用户ID",
        "SeriousDlqin2yrs":"好坏客户",
        "RevolvingUtilizationOfUnsecuredLines":"可用额度比值",
        "age":"年龄",
        "NumberOfTime30-59DaysPastDueNotWorse":"逾期30-59天笔数",
        "DebtRatio":"负债率",
        "MonthlyIncome":"月收入",
        "NumberOfOpenCreditLinesAndLoans":"信贷数量",
        "NumberOfTimes90DaysLate":"逾期90天笔数",
        "NumberRealEstateLoansOrLines":"固定资产贷款量",
        "NumberOfTime60-89DaysPastDueNotWorse":"逾期60-89天笔数",
        "NumberOfDependents":"家属数量"}
df.rename(columns=states,inplace=True)

处理后的表

03|数据预处理:

数据预处理主要是对一些缺失值以及异常值进行处理,先利用df.info()看看有没有缺失值。

3.1缺失值处理

代码语言:javascript
复制
df.info()
------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 12 columns):
用户ID          150000 non-null int64
好坏客户          150000 non-null int64
可用额度比值        150000 non-null float64
年龄            150000 non-null int64
逾期30-59天笔数    150000 non-null int64
负债率           150000 non-null float64
月收入           120269 non-null float64
信贷数量          150000 non-null int64
逾期90天笔数       150000 non-null int64
固定资产贷款量       150000 non-null int64
逾期60-89天笔数    150000 non-null int64
家属数量          146076 non-null float64
dtypes: float64(4), int64(8)

看到总共有150000条数据,其中变量月收入和家属数量有缺失值。

代码语言:javascript
复制
print("月收入缺失比:{:.2%}".format((150000-120269)/150000))
print("家属数量 缺失比:{:.2%}".format((150000-146076)/150000))
----------------------------------------
月收入缺失比:19.82%
家属数量缺失比:2.62%

关于缺失值我们一般的处理方法有直接删除、利用平均值、中位数、众数进行填充。

月收入缺失比比较高,不能直接删除,利用填充平均值的方法进行补充,家属数量的缺失比只有2.6%,直接删除。

代码语言:javascript
复制
#缺失值填充
df=df.fillna({"月收入":df["月收入"].mean()})
#缺失值删除
df1=df.dropna()

3.2异常值处理

异常值处理中我们首先需要对异常值进行检测,采用的方法是箱形图。

代码语言:javascript
复制
x1=df1["可用额度比值"]
x2=df1["负债率"]
fig=plt.figure(1)
ax=fig.add_subplot(111)
ax.boxplot([x1,x2])
ax.set_xticklabels(["可用额度比值","负债率"])

可用额度的比值是该客户的可用额度比总额度的比值,所以值不应该大于1,大于1的部分进行删除。

代码语言:javascript
复制
plt.rcParams["font.sans-serif"]='SimHei'
x3=df1["年龄"]
fig=plt.figure(2)
ax1=fig.add_subplot(111)
ax1.boxplot(x3)
ax1.set_xticklabels("年龄")

年龄不可能有0岁,把等于0的删除。

代码语言:javascript
复制
x4=df1["逾期30-59天笔数"]
x5=df1["逾期60-89天笔数"]
x6=df1["逾期90天笔数"]
fig=plt.figure(3)
ax=fig.add_subplot(111)
ax.boxplot([x4,x5,x6])
ax.set_xticklabels(["逾期30-59天笔数","逾期60-89天笔数","逾期90天笔数"])

逾期天数大于80的均算作异常值,进行删除。

代码语言:javascript
复制
x7=df1["信贷数量"]
x8=df1["固定资产贷款量"]
fig=plt.figure(4)
ax=fig.add_subplot(111)
ax.boxplot([x7,x8])
ax.set_xticklabels(["信贷数量","固定资产贷款量"])

固定资产贷款数量大于50的算作异常值,删除。

代码语言:javascript
复制
#异常值过滤
df1=df1[df1["可用额度比值"]<=1]
df1=df1[df1["年龄"]>0]
df1=df1[df1["逾期30-59天笔数"]<80]
df1=df1[df1["固定资产贷款量"]<50]

04|探索性分析:

针对用户的年龄、月收入、负债率等指标进行分析,看坏账用户与哪些指标有关。

4.1单变量分析

先来看看好坏客户的整体情况。

代码语言:javascript
复制
grouped=df1["用户ID"].groupby(df1["好坏客户"]).count()
print("坏客户占比:{:.2%}".format(grouped[1]/grouped[0]))
grouped.plot(kind="bar")
----------------

坏客户占比:6.34%
代码语言:javascript
复制
代码语言:javascript
复制
age_cut=pd.cut(df1["年龄"],5)
age_cut_grouped=df1["好坏客户"].groupby(age_cut).count()
age_cut_grouped1=df1["好坏客户"].groupby(age_cut).sum()
df2=pd.merge(pd.DataFrame(age_cut_grouped), pd.DataFrame(age_cut_grouped1),right_index=True,left_index=True)
df2.rename(columns={"好坏客户_x":"好客户","好坏客户_y":"坏客户"},inplace=True)
df2.insert(2,"坏客户率",df2["坏客户"]/df2["好客户"])
ax1=df2[["好客户","坏客户"]].plot.bar()
ax1.set_xticklabels(df2.index,rotation=15)
ax1.set_ylabel("客户数")
ax1.set_title("年龄与好坏客户数分布图")
代码语言:javascript
复制
ax11=df2["坏客户率"].plot()
ax11.set_ylabel("坏客户率")
ax11.set_title("坏客户率随年龄的变化趋势图")

通过上面的年龄-好坏客户分布图和坏客户率与年龄变化图可以看出,38-55岁这一部分人中好客户和坏客户的绝对数量均是top1,随着年龄的增长,坏客户率在降低,且38-72之间降低最快。

代码语言:javascript
复制
cut_bins=[0,5000,10000,15000,20000,100000]
month_cut=pd.cut(df1["月收入"],cut_bins)
month_cut_grouped=df1["好坏客户"].groupby(month_cut).count()
month_cut_grouped1=df1["好坏客户"].groupby(month_cut).sum()
df3=pd.merge(pd.DataFrame(month_cut_grouped), pd.DataFrame(month_cut_grouped1),right_index=True,left_index=True)
df3.rename(columns={"好坏客户_x":"好客户","好坏客户_y":"坏客户"},inplace=True)
df3.insert(2,"坏客户率",df3["坏客户"]/df3["好客户"])
ax23=df3[["好客户","坏客户"]].plot.bar()
ax23.set_xticklabels(df3.index,rotation=15)
ax23.set_ylabel("客户数")
ax23.set_title("好坏客户数与月收入关系")
代码语言:javascript
复制
ax231=df3["坏客户率"].plot()
ax231.set_ylabel("坏客户率")
ax231.set_title("月收入与坏客户率关系")

好坏客户的绝对量级主要集中在月收入在10000以下的群体中,月收入在0-15000之间,坏客户率随着月收入的增加而降低,之后进入平稳,当月收入超过20000时,坏客户率又开始上升。这可能是在月收入在15000以下的群体中,大部分的收入来源比较固定,收入越多,坏账可能性越低。而月收入大于20000的这一部分人的的可能不是从事普通工作的,收入不太固定,所以坏账的可能性比较大。

代码语言:javascript
复制
cut_bins=[0,2,4,20]
family_cut=pd.cut(df1["家属数量"],cut_bins)
family_cut_grouped=df1["好坏客户"].groupby(family_cut).count()
family_cut_grouped1=df1["好坏客户"].groupby(family_cut).sum()
df4=pd.merge(pd.DataFrame(family_cut_grouped), pd.DataFrame(family_cut_grouped1),right_index=True,left_index=True)
df4.rename(columns={"好坏客户_x":"好客户","好坏客户_y":"坏客户"},inplace=True)
df4.insert(2,"坏客户率",df4["坏客户"]/df4["好客户"])
ax24=df4[["好客户","坏客户"]].plot.bar()
ax24.set_xticklabels(df4.index,rotation=15)
ax24.set_ylabel("客户数")
ax24.set_title("好坏客户数与家属数量关系")
代码语言:javascript
复制
ax241=df4["坏客户率"].plot()
ax241.set_ylabel("坏客户率")
ax241.set_title("坏客户率与家属数量的关系")

好坏客户的绝对量级集中在家属数量0-2之间,随着家属数量的增加,坏账的可能性也就越大。这也可以理解,家属数量越大,需要的支出就比较大,更容易坏账。

单变量的分析思路都差不多,主要就是看某一个自变量和因变量之间的关系,其他变量大家可以自行练习。

4.2多变量分析

多变量分析主要是分析变量之间的关系。

代码语言:javascript
复制
plt.rcParams["font.sans-serif"]='SimHei'
plt.rcParams['axes.unicode_minus'] = False
corr = df1.corr()#计算各变量的相关性系数
xticks = list(corr.index)#x轴标签
yticks = list(corr.index)#y轴标签
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
sns.heatmap(corr, annot=True, cmap="rainbow",ax=ax1,linewidths=.5, annot_kws={'size': 9, 'weight': 'bold', 'color': 'blue'})
ax1.set_xticklabels(xticks, rotation=35, fontsize=10)
ax1.set_yticklabels(yticks, rotation=0, fontsize=10)
plt.show()

我们用热力图来表示不同变量之间的关系,单元格颜色越深,代表该单元格交叉的两个变量相关性越强。

注意区分相关关系和因果关系。

变量逾期30-59天笔数和固定资产贷款量的相关系数最大为0.43,可用额度比值和信贷数量的相关系数也为0.34,可能是这个人的贷款频次多,比较活跃,银行给了更多的额度,但是他每次贷款的额度较低,所以就会出现可用额度比值较高。

本篇只是对数据做了一个基本的探索性分析,后续会针对该批数据进行建模,对每一个用户进行打分,以此来评判每个用户的信用等级,合理的预防坏账的发生。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 俊红的数据分析之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01|背景:
  • 02|导入数据:
  • 03|数据预处理:
    • 3.1缺失值处理
      • 3.2异常值处理
      • 04|探索性分析:
        • 4.1单变量分析
          • 4.2多变量分析
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档