阅读之前看这里👉:博主是正在学习数据分析的一员,博客记录的是在学习过程中一些总结,也希望和大家一起进步,在记录之时,未免存在很多疏漏和不全,如有问题,还请私聊博主指正。
博客地址:天阑之蓝的博客,学习过程中不免有困难和迷茫,希望大家都能在这学习的过程中肯定自己,超越自己,最终创造自己。
项目背景:
因信用卡使用给人们带来便利,越来越多的人使用信用卡。信用卡要求人们按时还款,若未按时还款,银行将收取一定的利息获益,因此各大银行为了抢占市场,最大化发展客户。但有一些客户可能会违约使银行利益受损,故控制违约情况显得迫在眉睫。本文通过预测某人在未来两年内遭遇财务困境的可能性,来提高自己在信用评分方面的水平。目标是建立一个借款人可以用来帮助做出最佳财务决策的模型。
本文主要从分析框架、数据处理和建立预测模型等几个方面进行分析和介绍:
1、明确分析需求
1.1数据介绍
本数据来kaggle数据集:
提供了25万借款人的历史数据,包括训练集、测试集以及数据集信息。
首先查看数据包含的文件:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import os
for dirname, _, filenames in os.walk('GiveMeSomeCredit'):
for filename in filenames:
print(os.path.join(dirname, filename))
结果:
GiveMeSomeCredit\cs-test.csv
GiveMeSomeCredit\cs-training.csv
GiveMeSomeCredit\Data Dictionary.xls
GiveMeSomeCredit\sampleEntry.csv
我们可以看到文件有训练集和测试集,以及一个资料字典,还有提交样例。
查看一下资料字典里的信息:
主要是讲的各字段所代表的名称,含义和类型。
各字段代表的含义:
字段名 | 字段含义 |
---|---|
SeriousDlqin2yrs | 逾期90天以上的标记,即目标变量,1逾期,0表示没有逾期 |
RevolvingUtilizationOfUnsecuredLines | 信用卡和个人信用额度的总余额,除房地产和汽车贷款等分期付款债务外,除以信用额度总和 |
age | 年龄 |
NumberOfTime30-59DaysPastDueNotWorse | 借款人逾期30-59天的次数,但在过去两年没有恶化。 |
DebtRatio | 每月的债务,赡养费,生活费除以每月的总收入 |
MonthlyIncome | 月收入 |
NumberOfOpenCreditLinesAndLoans | 未偿还贷款的数量(如汽车贷款或抵押贷款的分期付款)和信用额度(如信用卡) |
NumberOfTimes90DaysLate | 借款人逾期90天或以上的次数。 |
NumberRealEstateLoansOrLines | 抵押贷款和房地产贷款的数量,包括房屋净值信贷额度 |
NumberOfTime60-89DaysPastDueNotWorse | 借款人逾期60-89天的次数,但在过去两年没有恶化。 |
NumberOfDependents | 家庭成员(不包括本身)的受养人数目(配偶、子女等) |
1.2明确分析思路
我们看到这些数据,到底有什么用呢,如何去分析呢?
首先明确目的:信用卡数据的各个信息对我们分析有什么用,最终目的什么,可以得到什么结论?
目的:通过这些数据预测信用卡客户违约的预测概率。
思路:通过分析数据之间的相关性,关联性,进行特征分析,选择合适的特征进行建模。
具体方法:查看各数据的统计信息,与是否逾期的关系,进行可视化表示,并得到相应的一些结论。
1.3 数据探索
首先看一下训练集中的内容:
df = pd.read_csv("GiveMeSomeCredit//cs-training.csv")
df.drop('Unnamed: 0',axis =1,inplace = True)
df.head()
为了看起来方便,将英文名替换成中文名
# 中文名替换
zh_label = ['目标变量','信用卡余额百分比','年龄','逾期30-59天的次数','每月开支占比','月收入','未偿还债务','抵押贷款和房地产贷款的数量','借款人逾期60-89天的次数','家庭成员数目']
en_label = df.columns.values.tolist()
zh_label_dict = dict(zip(en_label,zh_label))
zh_label_dict
df.rename(columns =zh_label_dict ,inplace=True)
df.head()
查看一下数据的基本信息:
数据大小
df.shape
(150000, 11) 共有150000个数据,特征向量有11个。
查看数据类型
df.dtypes.value_counts()
int64 7
float64 4
dtype: int64
一共有7个特征是整型,4个特征是浮点型。
数据信息
df.info()
观察到部分数据有缺失,所以接下来需要对缺失值的处理
1.4数据清洗和处理
查看缺失值
df.isnull().sum()[df.isnull().sum() != 0]
月收入 29731
家庭成员数目 3924
可以看到月收入和家庭成员数目有缺失,一般数据缺失有几种处理方法:
- 直接删除
- 用众数、中位数等进行替换
- 根据变量之间的相关关系填补缺失值
不过考虑到总数为15万,家庭成员数目占比较小,缺失数据可以删除。月收入应当是一个重要的因素,且占比不算小,可以根据变量之间的相关关系填补缺失值。
采用随机森林法:
# 用随机森林对缺失值预测填充函数
def set_missing(df):
# 把已有的数值型特征取出来
process_df = df.iloc[:,[5,0,1,2,3,4,6,7,8,9]]
# 分成已知该特征和未知该特征两部分
# dataframe.values获取的是dataframe中的数据为数组array
known = process_df[process_df.月收入.notnull()].values
unknown = process_df[process_df.月收入.isnull()].values
# X为已知MonthlyIncome的特征属性值
X = known[:, 1:]
# y为结果标签值MonthlyIncome
y = known[:, 0]
# X与y用于训练随机森林模型,fit到RandomForestRegressor之中
rfr = RandomForestRegressor(random_state=0, n_estimators=200,max_depth=3,n_jobs=-1)
rfr.fit(X,y)
# 用得到的模型进行未知特征值预测
predicted = rfr.predict(unknown[:, 1:]).round(0)
# 用得到的预测结果填补原缺失数据
df.loc[(df.月收入.isnull()), '月收入'] = predicted
return df
df=set_missing(df) # 用随机森林填补比较多的缺失值
df=df.dropna() # 删除比较少的缺失值
df = df.drop_duplicates() # 删除重复项
df.info()
0 目标变量 145563 non-null int64
1 信用卡余额百分比 145563 non-null float64
2 年龄 145563 non-null int64
3 逾期30-59天的次数 145563 non-null int64
4 每月开支占比 145563 non-null float64
5 月收入 145563 non-null float64
6 未偿还债务 145563 non-null int64
7 逾期90天或以上的次数 145563 non-null int64
8 抵押贷款和房地产贷款的数量 145563 non-null int64
9 借款人逾期60-89天的次数 145563 non-null int64
10 家庭成员数目 145563 non-null float64
可以看到数量变成了145563个了。
观察正负样本数量是否大致相等
df.目标变量.value_counts()
0 135732
1 9831
可以看到大约为13比1的情况
异常值检测
缺失值处理完毕后,我们还需要进行异常值处理。异常值是指明显偏离大多数抽样数据的数值,比如个人客户的年龄为0时,通常认为该值为异常值。找出样本总体中的异常值,通常采用离群值检测的方法。
df["年龄"].describe()
count 145563.000000
mean 52.110701
std 14.567652
min 0.000000
25% 41.000000
50% 52.000000
75% 62.000000
max 107.000000
我们可以看到最小值为0,所以需要对其异常值处理。应当删掉此异常值。
df.drop(df[(df['年龄'] == 0)].index.tolist(),inplace = True)
df["年龄"<