债务违约预测之二:图形探索

%matplotlib inline
import pandas as pd
import numpy as np 
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.gridspec as gridspec
pd.set_option("display.max_columns",101)
pd.set_option('display.float_format', lambda x: '%.5f' % x) #为了直观的显示数字,不采用科学计数法
pd.options.display.max_rows = 15 #最多显示15行
import warnings
warnings.filterwarnings('ignore') #为了整洁,去除弹出的warnings
import pandas as pd

df=pd.read_csv( 'cs-training.csv')
df = df.drop(df.columns[0],axis=1)
df=df[df.age>=18]

债务违约预测之一:数据探索中,按各个属性对借贷者分组,再分析其违约率。现在换一个角度,分为违约者和未违约两类,再查看两组人群中各个属性的分布。

features=df.columns[1:]
features
Index(['RevolvingUtilizationOfUnsecuredLines', 'age',
       'NumberOfTime30-59DaysPastDueNotWorse', 'DebtRatio', 'MonthlyIncome',
       'NumberOfOpenCreditLinesAndLoans', 'NumberOfTimes90DaysLate',
       'NumberRealEstateLoansOrLines', 'NumberOfTime60-89DaysPastDueNotWorse',
       'NumberOfDependents'],
      dtype='object')
plt.figure(figsize=(12,28*4))
gs = gridspec.GridSpec(28, 1)
#针对违约者和未违约者的每个属性,绘制直方图
for i, cn in enumerate(features):
    ax = plt.subplot(gs[i])
    sns.distplot(df[cn][df.SeriousDlqin2yrs == 1], bins=50,color='red')
    sns.distplot(df[cn][df.SeriousDlqin2yrs == 0], bins=50,color='blue')
    ax.set_xlabel('')
    ax.set_title('histogram of feature: ' + str(cn))
plt.show()

出现 'max must be larger than min in range parameter.'是因为有的列存在空值。

df.isnull().sum()

MonthlyIncome为空的记录较多,为了保持数据的完整,没有删掉,用平均值填充

df['MonthlyIncome'].fillna(df['MonthlyIncome'].mean(), inplace=True)
df['NumberOfDependents'].fillna(df['NumberOfDependents'].mode(), inplace=True)
#NumberOfDependents字段,用众数df['NumberOfDependents'].mode()来填充
df.isnull().sum() #空值还是存在,为什么呢
SeriousDlqin2yrs                           0
RevolvingUtilizationOfUnsecuredLines       0
age                                        0
NumberOfTime30-59DaysPastDueNotWorse       0
DebtRatio                                  0
MonthlyIncome                              0
NumberOfOpenCreditLinesAndLoans            0
NumberOfTimes90DaysLate                    0
NumberRealEstateLoansOrLines               0
NumberOfTime60-89DaysPastDueNotWorse       0
NumberOfDependents                      3924
dtype: int64
type(df['NumberOfDependents'].mode()) 
    pandas.core.series.Series
 #mode()返回的是一个Series,而不是单一的值,要取其中的元素来填充
df['NumberOfDependents'].fillna(df['NumberOfDependents'].mode()[0], inplace=True)#填补成功
sns.distplot(df['RevolvingUtilizationOfUnsecuredLines'][(df.SeriousDlqin2yrs == 1) & (df.RevolvingUtilizationOfUnsecuredLines)], bins=20,color='red')
sns.distplot(df['RevolvingUtilizationOfUnsecuredLines'][(df.SeriousDlqin2yrs == 0) & (df.RevolvingUtilizationOfUnsecuredLines)], bins=20,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0x10229a58>
output_15_1.png

图形缩成小小的一条,因为取值范围是0到50000多,x轴的范围太大了,而大部分值都在0附近,所以无法清晰显示。

df['RevolvingUtilizationOfUnsecuredLines'].describe() #看该属性的数值分布
count   149999.00000
mean         6.04847
std        249.75620
min          0.00000
25%          0.02987
50%          0.15418
75%          0.55904
max      50708.00000
Name: RevolvingUtilizationOfUnsecuredLines, dtype: float64
df[['RevolvingUtilizationOfUnsecuredLines']].boxplot(sym='r*') #用箱型图查看异常值
<matplotlib.axes._subplots.AxesSubplot at 0x100f1828>
output_18_1.png
p=df[['RevolvingUtilizationOfUnsecuredLines']].boxplot(return_type='dict')
#return_type='dict'时,会返回数据集的异常值
outliers=p['fliers'][0].get_xydata()#get_xydata()把异常值返回到一个二维数组中
outliers.shape
(763, 2)
outliers[:,1:].min() #看看最小的异常值是多少
1.3534146969999998
sns.distplot(df['RevolvingUtilizationOfUnsecuredLines'][(df.SeriousDlqin2yrs == 1) & (df.RevolvingUtilizationOfUnsecuredLines<1.4)], bins=20,color='red')
sns.distplot(df['RevolvingUtilizationOfUnsecuredLines'][(df.SeriousDlqin2yrs == 0) & (df.RevolvingUtilizationOfUnsecuredLines<1.4)], bins=20,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0x1027f5f8>
output_21_1.png

未违约人群,RevolvingUtilizationOfUnsecuredLines属性的最高频率在0附近;违约人群,RevolvingUtilizationOfUnsecuredLines的最高频率在1附近。

#计算每个属性的异常值数量和最小的异常值
col_min={}
for  feature in features:
    p=df[[feature]].boxplot(return_type='dict')
    outliers=p['fliers'][0].get_xydata()
    pmin=outliers[:,1:].min()
    col_min[feature]=[outliers.shape[0],pmin]
output_23_0.png
col_min
{'DebtRatio': [31311, 1.9080459769999998],
 'MonthlyIncome': [9149, 12646.0],
 'NumberOfDependents': [13336, 3.0],
 'NumberOfOpenCreditLinesAndLoans': [3980, 21.0],
 'NumberOfTime30-59DaysPastDueNotWorse': [23981, 1.0],
 'NumberOfTime60-89DaysPastDueNotWorse': [7604, 1.0],
 'NumberOfTimes90DaysLate': [8338, 1.0],
 'NumberRealEstateLoansOrLines': [793, 6.0],
 'RevolvingUtilizationOfUnsecuredLines': [763, 1.3534146969999998],
 'age': [45, 97.0]}
#结合异常值和该属性上的数值分布,选定取值范围作图。因为每个属性的选取范围和bins不同,所以不进行统一绘图,
而是一个一个绘制。
sns.distplot(df['DebtRatio'][(df.SeriousDlqin2yrs == 1) & (df.DebtRatio<5)], bins=20,color='red')
sns.distplot(df['DebtRatio'][(df.SeriousDlqin2yrs == 0) & (df.DebtRatio<5)], bins=20,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0xa7cfef0>
output_25_1.png
两组人群在DebtRatio属性上的分布相似,最高频率在0附近,后逐渐降低
sns.distplot(df['NumberOfOpenCreditLinesAndLoans'][(df.SeriousDlqin2yrs == 1) & (df.NumberOfOpenCreditLinesAndLoans<30)], bins=30,color='red')
sns.distplot(df['NumberOfOpenCreditLinesAndLoans'][(df.SeriousDlqin2yrs == 0) & (df.NumberOfOpenCreditLinesAndLoans<30)], bins=30,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0x11eca3c8>
output_27_1.png
在NumberOfOpenCreditLinesAndLoans属性上,两组人群分布相似,最高频率都是5-8之间
sns.distplot(df['age'][df.SeriousDlqin2yrs == 1] ,bins=50,color='red')
sns.distplot(df['age'][df.SeriousDlqin2yrs == 0], bins=50,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0x137bbfd0>
output_29_1.png
sns.distplot(df['NumberOfTime30-59DaysPastDueNotWorse'][(df.SeriousDlqin2yrs == 1) & (df['NumberOfTime30-59DaysPastDueNotWorse']<10)], bins=10,color='red')
sns.distplot(df['NumberOfTime30-59DaysPastDueNotWorse'][(df.SeriousDlqin2yrs == 0) & (df['NumberOfTime30-59DaysPastDueNotWorse']<10)], bins=10,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0xbb45908>
output_30_1.png
sns.distplot(df['NumberOfTime60-89DaysPastDueNotWorse'][(df.SeriousDlqin2yrs == 1) & (df['NumberOfTime60-89DaysPastDueNotWorse']<10)], bins=10,color='red')
sns.distplot(df['NumberOfTime60-89DaysPastDueNotWorse'][(df.SeriousDlqin2yrs == 0) & (df['NumberOfTime60-89DaysPastDueNotWorse']<10)], bins=10,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0xbf33940>
output_31_1.png
sns.distplot(df['NumberOfTimes90DaysLate'][(df.SeriousDlqin2yrs == 1) & (df.NumberOfTimes90DaysLate<10)], bins=10,color='red')
sns.distplot(df['NumberOfTimes90DaysLate'][(df.SeriousDlqin2yrs == 0) & (df.NumberOfTimes90DaysLate<10)], bins=10,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0xa5992b0>
output_32_1.png
sns.distplot(df['NumberRealEstateLoansOrLines'][(df.SeriousDlqin2yrs == 1) & (df.NumberRealEstateLoansOrLines<10)], bins=10,color='red')
sns.distplot(df['NumberRealEstateLoansOrLines'][(df.SeriousDlqin2yrs == 0) & (df.NumberRealEstateLoansOrLines<10)], bins=10,color='blue')
<matplotlib.axes._subplots.AxesSubplot at 0xa7aa2e8>
output_33_1.png
其余几个属性上,两类人群的分布都是相近的,不再赘述。和本文采用的是不同分析方法,
前者按各个属性对借贷者分组,查看不同类别在每一组的分布。本文是先进行分类,再查看两个类别中各个属性的分布。
。第一种方法使用数字,能看出更多信息。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,852评论 6 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • 这张导图是有机化学中最基础的几种物质。中心图是脸谱,因为有机化学对于化学就像是脸谱对于京剧一样重要。第一分支是甲烷...
    陈虹宇_e51c阅读 2,082评论 0 1