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

浏览: 1617

image.png

总第92篇

01|背景:

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

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

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

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

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

02|导入数据:

#导入相关库
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。

print(df.columns)
----------------------------
Index(['ID', 'SeriousDlqin2yrs', 'RevolvingUtilizationOfUnsecuredLines', 'age',
     
'NumberOfTime30-59DaysPastDueNotWorse', 'DebtRatio', 'MonthlyIncome',
     
'NumberOfOpenCreditLinesAndLoans', 'NumberOfTimes90DaysLate',
     
'NumberRealEstateLoansOrLines', 'NumberOfTime60-89DaysPastDueNotWorse',
     
'NumberOfDependents'],
     dtype
='object')
#数据指标解读
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转化为中文,

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)

image.png

03|数据预处理:

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

3.1缺失值处理

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条数据,其中变量月收入和家属数量有缺失值。

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

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

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

#缺失值填充
df
=df.fillna({"月收入":df["月收入"].mean()})
#缺失值删除
df1
=df.dropna()

3.2异常值处理

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

x1=df1["可用额度比值"]
x2
=df1["负债率"]
fig
=plt.figure(1)
ax
=fig.add_subplot(111)
ax
.boxplot([x1,x2])
ax
.set_xticklabels(["可用额度比值","负债率"])

image.png

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


plt.rcParams["font.sans-serif"]='SimHei'
x3
=df1["年龄"]
fig
=plt.figure(2)
ax1
=fig.add_subplot(111)
ax1
.boxplot(x3)
ax1
.set_xticklabels("年龄")

image.png

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

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天笔数"])

image.png

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

x7=df1["信贷数量"]
x8
=df1["固定资产贷款量"]
fig
=plt.figure(4)
ax
=fig.add_subplot(111)
ax
.boxplot([x7,x8])
ax
.set_xticklabels(["信贷数量","固定资产贷款量"])

image.png

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


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

04|探索性分析:

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

4.1单变量分析

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

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

坏客户占比:6.34%

image.png

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("年龄与好坏客户数分布图")

image.png

ax11=df2["坏客户率"].plot()
ax11.set_ylabel("坏客户率")
ax11.set_title("坏客户率随年龄的变化趋势图")

image.png

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


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("好坏客户数与月收入关系")

image.png

ax231=df3["坏客户率"].plot()
ax231.set_ylabel("坏客户率")
ax231.set_title("月收入与坏客户率关系")

image.png

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


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("好坏客户数与家属数量关系")

image.png

ax241=df4["坏客户率"].plot()
ax241.set_ylabel("坏客户率")
ax241.set_title("坏客户率与家属数量的关系")

image.png

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

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

4.2多变量分析

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

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()

image.png

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


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

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

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

image.png

推荐 0
本文由 张俊红 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册