From d8b8b063eb19d499b0b515f7c2b6eefda153ca3a Mon Sep 17 00:00:00 2001 From: MYP Date: Sat, 5 Sep 2020 09:32:37 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E5=86=85=E5=AE=B9=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FinancialRiskControl/Task1 赛题理解.md | 494 +++++++ FinancialRiskControl/Task2 数据分析.md | 1770 ++++++++++++++++++++++++ 2 files changed, 2264 insertions(+) create mode 100644 FinancialRiskControl/Task1 赛题理解.md create mode 100644 FinancialRiskControl/Task2 数据分析.md diff --git a/FinancialRiskControl/Task1 赛题理解.md b/FinancialRiskControl/Task1 赛题理解.md new file mode 100644 index 0000000..dc29dfc --- /dev/null +++ b/FinancialRiskControl/Task1 赛题理解.md @@ -0,0 +1,494 @@ +## Task1 赛题理解 + +Tip:本次新人赛是Datawhale与天池联合发起的0基础入门系列赛事第四场 —— 零基础入门金融风控之贷款违约预测挑战赛。 + +赛题以金融风控中的个人信贷为背景,要求选手根据贷款申请人的数据信息预测其是否有违约的可能,以此判断是否通过此项贷款,这是一个典型的分类问题。通过这道赛题来引导大家了解金融风控中的一些业务背景,解决实际问题,帮助竞赛新人进行自我练习、自我提高。 + +地址: + +### 1.1 学习目标 +理解赛题数据和目标,清楚评分体系。 + +完成相应报名,下载数据和结果提交打卡(可提交示例结果),熟悉比赛流程 + + +### 1.2 了解赛题 +- 赛题概况 +- 数据概况 +- 预测指标 +- 分析赛题 + +### 1.2.1 赛题概况 + +##### 比赛要求参赛选手根据给定的数据集,建立模型,预测金融风险。 +赛题以预测金融风险为任务,数据集报名后可见并可下载,该数据来自某信贷平台的贷款记录,总数据量超过120w,包含47列变量信息,其中15列为匿名变量。为了保证比赛的公平性,将会从中抽取80万条作为训练集,20万条作为测试集A,20万条作为测试集B,同时会对employmentTitle、purpose、postCode和title等信息进行脱敏。 + + +通过这道赛题来引导大家走进金融风控数据竞赛的世界,主要针对于于竞赛新人进行自我练习、自我提高。 + +### 1.2.2 数据概况 + +一般而言,对于数据在比赛界面都有对应的数据概况介绍(匿名特征除外),说明列的性质特征。了解列的性质会有助于我们对于数据的理解和后续分析。 Tip:匿名特征,就是未告知数据列所属的性质的特征列。 + +train.csv + +- id 为贷款清单分配的唯一信用证标识 +- loanAmnt 贷款金额 +- term 贷款期限(year) +- interestRate 贷款利率 +- installment 分期付款金额 +- grade 贷款等级 +- subGrade 贷款等级之子级 +- employmentTitle 就业职称 +- employmentLength 就业年限(年) +- homeOwnership 借款人在登记时提供的房屋所有权状况 +- annualIncome 年收入 +- verificationStatus 验证状态 +- issueDate 贷款发放的月份 +- purpose 借款人在贷款申请时的贷款用途类别 +- postCode 借款人在贷款申请中提供的邮政编码的前3位数字 +- regionCode 地区编码 +- dti 债务收入比 +- delinquency_2years 借款人过去2年信用档案中逾期30天以上的违约事件数 +- ficoRangeLow 借款人在贷款发放时的fico所属的下限范围 +- ficoRangeHigh 借款人在贷款发放时的fico所属的上限范围 +- openAcc 借款人信用档案中未结信用额度的数量 +- pubRec 贬损公共记录的数量 +- pubRecBankruptcies 公开记录清除的数量 +- revolBal 信贷周转余额合计 +- revolUtil 循环额度利用率,或借款人使用的相对于所有可用循环信贷的信贷金额 +- totalAcc 借款人信用档案中当前的信用额度总数 +- initialListStatus 贷款的初始列表状态 +- applicationType 表明贷款是个人申请还是与两个共同借款人的联合申请 +- earliesCreditLine 借款人最早报告的信用额度开立的月份 +- title 借款人提供的贷款名称 +- policyCode 公开可用的策略_代码=1新产品不公开可用的策略_代码=2 +- n系列匿名特征 匿名特征n0-n14,为一些贷款人行为计数特征的处理 + + +### 1.2.3 预测指标 + +竞赛采用AUC作为评价指标。AUC(Area Under Curve)被定义为 ROC曲线 下与坐标轴围成的面积。 + +##### 分类算法常见的评估指标如下: + +1、混淆矩阵(Confuse Matrix) +- (1)若一个实例是正类,并且被预测为正类,即为真正类TP(True Positive ) +- (2)若一个实例是正类,但是被预测为负类,即为假负类FN(False Negative ) +- (3)若一个实例是负类,但是被预测为正类,即为假正类FP(False Positive ) +- (4)若一个实例是负类,并且被预测为负类,即为真负类TN(True Negative ) + +2、准确率(Accuracy) +准确率是常用的一个评价指标,但是不适合样本不均衡的情况。 +$$Accuracy = \frac{TP + TN}{TP + TN + FP + FN}$$ + +3、精确率(Precision) +又称查准率,正确预测为正样本(TP)占预测为正样本(TP+FP)的百分比。 +$$Precision = \frac{TP}{TP + FP}$$ + +4、召回率(Recall) +又称为查全率,正确预测为正样本(TP)占正样本(TP+FN)的百分比。 +$$Recall = \frac{TP}{TP + FN}$$ + +5、F1 Score +精确率和召回率是相互影响的,精确率升高则召回率下降,召回率升高则精确率下降,如果需要兼顾二者,就需要精确率、召回率的结合F1 Score。 +$$F1-Score = \frac{2}{\frac{1}{Precision} + \frac{1}{Recall}}$$ + +6、P-R曲线(Precision-Recall Curve) +P-R曲线是描述精确率和召回率变化的曲线 + +![p-r.png](https://img-blog.csdnimg.cn/20200905091949616.png) + +7、ROC(Receiver Operating Characteristic) +- ROC空间将假正例率(FPR)定义为 X 轴,真正例率(TPR)定义为 Y 轴。 + +TPR:在所有实际为正例的样本中,被正确地判断为正例之比率。 +$$TPR = \frac{TP}{TP + FN}$$ +FPR:在所有实际为负例的样本中,被错误地判断为正例之比率。 +$$FPR = \frac{FP}{FP + TN}$$ + +![roc.png](https://img-blog.csdnimg.cn/20200905092031110.png) + +8、AUC(Area Under Curve) +AUC(Area Under Curve)被定义为 ROC曲线 下与坐标轴围成的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。AUC越接近1.0,检测方法真实性越高;等于0.5时,则真实性最低,无应用价值。 + + +##### 对于金融风控预测类常见的评估指标如下: + +1、KS(Kolmogorov-Smirnov) +K-S曲线与ROC曲线类似,不同在于 +- ROC曲线将真正例率和假正例率作为横纵轴 +- K-S曲线将真正例率和假正例率都作为纵轴,横轴则由选定的阈值来充当。 +公式如下: +$$KS=max(TPR-FPR)$$ +KS不同代表的不同情况,一般情况KS值越大,模型的区分能力越强,但是也不是越大模型效果就越好,如果KS过大,模型可能存在异常,所以当KS值过高可能需要检查模型是否过拟合。以下为KS值对应的模型情况,但此对应不是唯一的,只代表大致趋势。 +- KS值<0.2,一般认为模型没有区分能力。 +- KS值[0.2,0.3],模型具有一定区分能力,勉强可以接受 +- KS值[0.3,0.5],模型具有较强的区分能力。 +- KS值大于0.75,往往表示模型有异常。 +2、ROC +3、AUC + +### 1.2.4. 赛题流程 + +![1_1.png](https://img-blog.csdnimg.cn/2020090509170561.png) + +### 1.3 代码示例 + +本部分为对于数据读取和指标评价的示例。 + +### 1.3.1 数据读取pandas + + +```python +import pandas as pd +``` + + +```python +train = pd.read_csv('train.csv') +testA = pd.read_csv('testA.csv') +``` + + +```python +print('Train data shape:',train.shape) +print('TestA data shape:',testA.shape) +``` + + Train data shape: (800000, 47) + TestA data shape: (200000, 48) + + + +```python +train.head() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
idloanAmntterminterestRateinstallmentgradesubGradeemploymentTitleemploymentLengthhomeOwnership...n5n6n7n8n9n10n11n12n13n14
0035000.0519.52917.97EE2320.02 years2...9.08.04.012.02.07.00.00.00.02.0
1118000.0518.49461.90DD2219843.05 years0...NaNNaNNaNNaNNaN13.0NaNNaNNaNNaN
2212000.0516.99298.17DD331698.08 years0...0.021.04.05.03.011.00.00.00.04.0
3311000.037.26340.96AA446854.010+ years1...16.04.07.021.06.09.00.00.00.01.0
443000.0312.99101.07CC254.0NaN1...4.09.010.015.07.012.00.00.00.04.0
+

5 rows × 47 columns

+
+ + + +### 1.3.2 分类指标评价计算示例 + + +```python +## 混淆矩阵 +import numpy as np +from sklearn.metrics import confusion_matrix +y_pred = [0, 1, 0, 1] +y_true = [0, 1, 1, 0] +print('混淆矩阵:\n',confusion_matrix(y_true, y_pred)) +``` + + 混淆矩阵: + [[1 1] + [1 1]] + + + +```python +## accuracy +from sklearn.metrics import accuracy_score +y_pred = [0, 1, 0, 1] +y_true = [0, 1, 1, 0] +print('ACC:',accuracy_score(y_true, y_pred)) +``` + + ACC: 0.5 + + + +```python +## Precision,Recall,F1-score +from sklearn import metrics +y_pred = [0, 1, 0, 1] +y_true = [0, 1, 1, 0] +print('Precision',metrics.precision_score(y_true, y_pred)) +print('Recall',metrics.recall_score(y_true, y_pred)) +print('F1-score:',metrics.f1_score(y_true, y_pred)) +``` + + Precision 0.5 + Recall 0.5 + F1-score: 0.5 + + + +```python +## P-R曲线 +import matplotlib.pyplot as plt +from sklearn.metrics import precision_recall_curve +y_pred = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1] +y_true = [0, 1, 1, 0, 1, 0, 1, 1, 0, 1] +precision, recall, thresholds = precision_recall_curve(y_true, y_pred) +plt.plot(precision, recall) +``` + + + + + [] + + + + +![output_29_1.png](https://img-blog.csdnimg.cn/20200905091758456.png) + + + +```python +## ROC曲线 +from sklearn.metrics import roc_curve +y_pred = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1] +y_true = [0, 1, 1, 0, 1, 0, 1, 1, 0, 1] +FPR,TPR,thresholds=roc_curve(y_true, y_pred) +plt.title('ROC') +plt.plot(FPR, TPR,'b') +plt.plot([0,1],[0,1],'r--') +plt.ylabel('TPR') +plt.xlabel('FPR') +``` + + + + + Text(0.5, 0, 'FPR') + + + + +![output_30_1.png](https://img-blog.csdnimg.cn/20200905091831243.png) + + + +```python +## AUC +import numpy as np +from sklearn.metrics import roc_auc_score +y_true = np.array([0, 0, 1, 1]) +y_scores = np.array([0.1, 0.4, 0.35, 0.8]) +print('AUC socre:',roc_auc_score(y_true, y_scores)) +``` + + AUC socre: 0.75 + + + +```python +## KS值 在实际操作时往往使用ROC曲线配合求出KS值 +from sklearn.metrics import roc_curve +y_pred = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1] +y_true = [0, 1, 1, 0, 1, 0, 1, 1, 1, 1] +FPR,TPR,thresholds=roc_curve(y_true, y_pred) +KS=abs(FPR-TPR).max() +print('KS值:',KS) +``` + + KS值: 0.5238095238095237 + + +### 1.4 经验总结 +赛题理解是开始比赛的第一步,赛题的理解有助于对竞赛全局的把握。通过赛题理解有助于对赛题的业务逻辑把握,对于后期的特征工程构建和模型选择都尤为重要。 +- 在开始比赛之前要对赛题进行充分的了解。 +- 比赛什么时候开始,什么时候结束,什么时候换B榜数据。 +- 和该比赛有没有类似的比赛可以参考借鉴。 +- 线上提交结果的次数往往是有限的,提前了解每日可以提交的次数。 +- 比赛使用的是什么评价指标,可以选择相同的评价指标作为线下验证的方式。 + + + +### 1.5 拓展知识——评分卡 +评分卡是一张拥有分数刻度会让相应阈值的表。信用评分卡是用于用户信用的一张刻度表。以下代码是一个非标准评分卡的代码流程,用于刻画用户的信用评分。评分卡是金融风控中常用的一种对于用户信用进行刻画的手段哦! + + +```python +#评分卡 不是标准评分卡 +def Score(prob,P0=600,PDO=20,badrate=None,goodrate=None): + P0 = P0 + PDO = PDO + theta0 = badrate/goodrate + B = PDO/np.log(2) + A = P0 + B*np.log(2*theta0) + score = A-B*np.log(prob/(1-prob)) + return score +``` + +END. +【 杨冰楠:Datawhale成员,金融风控爱好者。】 + + +关于Datawhale: + +Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale 以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时 Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + +本次数据挖掘路径学习,专题知识将在天池分享,详情可关注Datawhale: +![logo.png](logo.png) diff --git a/FinancialRiskControl/Task2 数据分析.md b/FinancialRiskControl/Task2 数据分析.md new file mode 100644 index 0000000..a0a6664 --- /dev/null +++ b/FinancialRiskControl/Task2 数据分析.md @@ -0,0 +1,1770 @@ +# Task2 数据分析 + +此部分为零基础入门金融风控的 Task2 数据分析部分,带你来了解数据,熟悉数据,为后续的特征工程做准备,欢迎大家后续多多交流。 + +赛题:零基础入门数据挖掘 - 零基础入门金融风控之贷款违约 + +目的: +- 1.EDA价值主要在于熟悉了解整个数据集的基本情况(缺失值,异常值),对数据集进行验证是否可以进行接下来的机器学习或者深度学习建模. + +- 2.了解变量间的相互关系、变量与预测值之间的存在关系。 + +- 3.为特征工程做准备 + +预测地址: + +## 2.1 学习目标 + +- 学习如何对数据集整体概况进行分析,包括数据集的基本情况(缺失值,异常值) +- 学习了解变量间的相互关系、变量与预测值之间的存在关系 +- 完成相应学习打卡任务 + + +## 2.2 内容介绍 + +- 数据总体了解: + - 读取数据集并了解数据集大小,原始特征维度; + - 通过info熟悉数据类型; + - 粗略查看数据集中各特征基本统计量; +- 缺失值和唯一值: + - 查看数据缺失值情况 + - 查看唯一值特征情况 +- 深入数据-查看数据类型 + - 类别型数据 + - 数值型数据 + - 离散数值型数据 + - 连续数值型数据 +- 数据间相关关系 + - 特征和特征之间关系 + - 特征和目标变量之间关系 +- 用pandas_profiling生成数据报告 + + +## 2.3 代码示例 + +### 2.3.1 导入数据分析及可视化过程需要的库 + + +```python +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import seaborn as sns +import datetime +import warnings +warnings.filterwarnings('ignore') +``` + + /Users/exudingtao/opt/anaconda3/lib/python3.7/site-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead. + import pandas.util.testing as tm + + +以上库都是pip install 安装就好,如果本机有python2,python3两个python环境傻傻分不清哪个的话,可以pip3 install 。或者直接在notebook中'!pip3 install ****'安装。 + +### 说明: +本次数据分析探索,尤其可视化部分均选取某些特定变量进行了举例,所以它只是一个方法的展示而不是整个赛题数据分析的解决方案。 + +### 2.3.2 读取文件 + + +```python +data_train = pd.read_csv('./train.csv') +``` + + +```python +data_test_a = pd.read_csv('./testA.csv') +``` + +#### 2.3.2.1读取文件的拓展知识 + + +- pandas读取数据时相对路径载入报错时,尝试使用os.getcwd()查看当前工作目录。 +- TSV与CSV的区别: + - 从名称上即可知道,TSV是用制表符(Tab,'\t')作为字段值的分隔符;CSV是用半角逗号(',')作为字段值的分隔符; + - Python对TSV文件的支持: + Python的csv模块准确的讲应该叫做dsv模块,因为它实际上是支持范式的分隔符分隔值文件(DSV,delimiter-separated values)的。 + delimiter参数值默认为半角逗号,即默认将被处理文件视为CSV。当delimiter='\t'时,被处理文件就是TSV。 +- 读取文件的部分(适用于文件特别大的场景) + - 通过nrows参数,来设置读取文件的前多少行,nrows是一个大于等于0的整数。 + - 分块读取 + + +```python +data_train_sample = pd.read_csv("./train.csv",nrows=5) +``` + + +```python +#设置chunksize参数,来控制每次迭代数据的大小 +chunker = pd.read_csv("./train.csv",chunksize=5) +for item in chunker: + print(type(item)) + # + print(len(item)) + #5 +``` + +### 2.3.3总体了解 + +#### 查看数据集的样本个数和原始特征维度 + + +```python +data_test_a.shape +``` + + + + + (200000, 48) + + + + +```python +data_train.shape +``` + + + + + (800000, 47) + + + + +```python +data_train.columns +``` + + + + + Index(['id', 'loanAmnt', 'term', 'interestRate', 'installment', 'grade', + 'subGrade', 'employmentTitle', 'employmentLength', 'homeOwnership', + 'annualIncome', 'verificationStatus', 'issueDate', 'isDefault', + 'purpose', 'postCode', 'regionCode', 'dti', 'delinquency_2years', + 'ficoRangeLow', 'ficoRangeHigh', 'openAcc', 'pubRec', + 'pubRecBankruptcies', 'revolBal', 'revolUtil', 'totalAcc', + 'initialListStatus', 'applicationType', 'earliesCreditLine', 'title', + 'policyCode', 'n0', 'n1', 'n2', 'n2.1', 'n4', 'n5', 'n6', 'n7', 'n8', + 'n9', 'n10', 'n11', 'n12', 'n13', 'n14'], + dtype='object') + + + +查看一下具体的列名,赛题理解部分已经给出具体的特征含义,这里方便阅读再给一下: +- id 为贷款清单分配的唯一信用证标识 +- loanAmnt 贷款金额 +- term 贷款期限(year) +- interestRate 贷款利率 +- installment 分期付款金额 +- grade 贷款等级 +- subGrade 贷款等级之子级 +- employmentTitle 就业职称 +- employmentLength 就业年限(年) +- homeOwnership 借款人在登记时提供的房屋所有权状况 +- annualIncome 年收入 +- verificationStatus 验证状态 +- issueDate 贷款发放的月份 +- purpose 借款人在贷款申请时的贷款用途类别 +- postCode 借款人在贷款申请中提供的邮政编码的前3位数字 +- regionCode 地区编码 +- dti 债务收入比 +- delinquency_2years 借款人过去2年信用档案中逾期30天以上的违约事件数 +- ficoRangeLow 借款人在贷款发放时的fico所属的下限范围 +- ficoRangeHigh 借款人在贷款发放时的fico所属的上限范围 +- openAcc 借款人信用档案中未结信用额度的数量 +- pubRec 贬损公共记录的数量 +- pubRecBankruptcies 公开记录清除的数量 +- revolBal 信贷周转余额合计 +- revolUtil 循环额度利用率,或借款人使用的相对于所有可用循环信贷的信贷金额 +- totalAcc 借款人信用档案中当前的信用额度总数 +- initialListStatus 贷款的初始列表状态 +- applicationType 表明贷款是个人申请还是与两个共同借款人的联合申请 +- earliesCreditLine 借款人最早报告的信用额度开立的月份 +- title 借款人提供的贷款名称 +- policyCode 公开可用的策略_代码=1新产品不公开可用的策略_代码=2 +- n系列匿名特征 匿名特征n0-n14,为一些贷款人行为计数特征的处理 + +通过info()来熟悉数据类型 + + +```python +data_train.info() +``` + + + RangeIndex: 800000 entries, 0 to 799999 + Data columns (total 47 columns): + # Column Non-Null Count Dtype + --- ------ -------------- ----- + 0 id 800000 non-null int64 + 1 loanAmnt 800000 non-null float64 + 2 term 800000 non-null int64 + 3 interestRate 800000 non-null float64 + 4 installment 800000 non-null float64 + 5 grade 800000 non-null object + 6 subGrade 800000 non-null object + 7 employmentTitle 799999 non-null float64 + 8 employmentLength 753201 non-null object + 9 homeOwnership 800000 non-null int64 + 10 annualIncome 800000 non-null float64 + 11 verificationStatus 800000 non-null int64 + 12 issueDate 800000 non-null object + 13 isDefault 800000 non-null int64 + 14 purpose 800000 non-null int64 + 15 postCode 799999 non-null float64 + 16 regionCode 800000 non-null int64 + 17 dti 799761 non-null float64 + 18 delinquency_2years 800000 non-null float64 + 19 ficoRangeLow 800000 non-null float64 + 20 ficoRangeHigh 800000 non-null float64 + 21 openAcc 800000 non-null float64 + 22 pubRec 800000 non-null float64 + 23 pubRecBankruptcies 799595 non-null float64 + 24 revolBal 800000 non-null float64 + 25 revolUtil 799469 non-null float64 + 26 totalAcc 800000 non-null float64 + 27 initialListStatus 800000 non-null int64 + 28 applicationType 800000 non-null int64 + 29 earliesCreditLine 800000 non-null object + 30 title 799999 non-null float64 + 31 policyCode 800000 non-null float64 + 32 n0 759730 non-null float64 + 33 n1 759730 non-null float64 + 34 n2 759730 non-null float64 + 35 n2.1 759730 non-null float64 + 36 n4 766761 non-null float64 + 37 n5 759730 non-null float64 + 38 n6 759730 non-null float64 + 39 n7 759730 non-null float64 + 40 n8 759729 non-null float64 + 41 n9 759730 non-null float64 + 42 n10 766761 non-null float64 + 43 n11 730248 non-null float64 + 44 n12 759730 non-null float64 + 45 n13 759730 non-null float64 + 46 n14 759730 non-null float64 + dtypes: float64(33), int64(9), object(5) + memory usage: 286.9+ MB + + +总体粗略的查看数据集各个特征的一些基本统计量 + + +```python +data_train.describe() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
idloanAmntterminterestRateinstallmentemploymentTitlehomeOwnershipannualIncomeverificationStatusisDefault...n5n6n7n8n9n10n11n12n13n14
count800000.000000800000.000000800000.000000800000.000000800000.000000799999.000000800000.0000008.000000e+05800000.000000800000.000000...759730.000000759730.000000759730.000000759729.000000759730.000000766761.000000730248.000000759730.000000759730.000000759730.000000
mean399999.50000014416.8188753.48274513.238391437.94772372005.3517140.6142137.613391e+041.0096830.199513...8.1079378.5759948.28295314.6224885.59234511.6438960.0008150.0033840.0893662.178606
std230940.2520158716.0861780.8558324.765757261.460393106585.6402040.6757496.894751e+040.7827160.399634...4.7992107.4005364.5616898.1246103.2161845.4841040.0300750.0620410.5090691.844377
min0.000000500.0000003.0000005.31000015.6900000.0000000.0000000.000000e+000.0000000.000000...0.0000000.0000000.0000001.0000000.0000000.0000000.0000000.0000000.0000000.000000
25%199999.7500008000.0000003.0000009.750000248.450000427.0000000.0000004.560000e+040.0000000.000000...5.0000004.0000005.0000009.0000003.0000008.0000000.0000000.0000000.0000001.000000
50%399999.50000012000.0000003.00000012.740000375.1350007755.0000001.0000006.500000e+041.0000000.000000...7.0000007.0000007.00000013.0000005.00000011.0000000.0000000.0000000.0000002.000000
75%599999.25000020000.0000003.00000015.990000580.710000117663.5000001.0000009.000000e+042.0000000.000000...11.00000011.00000010.00000019.0000007.00000014.0000000.0000000.0000000.0000003.000000
max799999.00000040000.0000005.00000030.9900001715.420000378351.0000005.0000001.099920e+072.0000001.000000...70.000000132.00000079.000000128.00000045.00000082.0000004.0000004.00000039.00000030.000000
+

8 rows × 42 columns

+
+ + + + +```python +data_train.head(3).append(data_train.tail(3)) +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
idloanAmntterminterestRateinstallmentgradesubGradeemploymentTitleemploymentLengthhomeOwnership...n5n6n7n8n9n10n11n12n13n14
0035000.0519.52917.97EE2320.02 years2...9.08.04.012.02.07.00.00.00.02.0
1118000.0518.49461.90DD2219843.05 years0...NaNNaNNaNNaNNaN13.0NaNNaNNaNNaN
2212000.0516.99298.17DD331698.08 years0...0.021.04.05.03.011.00.00.00.04.0
7999977999976000.0313.33203.12CC32582.010+ years1...4.026.04.010.04.05.00.00.01.04.0
79999879999819200.036.92592.14AA4151.010+ years0...10.06.012.022.08.016.00.00.00.05.0
7999997999999000.0311.06294.91BB313.05 years0...3.04.04.08.03.07.00.00.00.02.0
+

6 rows × 47 columns

+
+ + + +### 2.3.4查看数据集中特征缺失值,唯一值等 + +查看缺失值 + + +```python +print(f'There are {data_train.isnull().any().sum()} columns in train dataset with missing values.') +``` + + There are 22 columns in train dataset with missing values. + + +上面得到训练集有22列特征有缺失值,进一步查看缺失特征中缺失率大于50%的特征 + + +```python +have_null_fea_dict = (data_train.isnull().sum()/len(data_train)).to_dict() +fea_null_moreThanHalf = {} +for key,value in have_null_fea_dict.items(): + if value > 0.5: + fea_null_moreThanHalf[key] = value +``` + + +```python +fea_null_moreThanHalf +``` + + + + + {} + + + +具体的查看缺失特征及缺失率 + + +```python +# nan可视化 +missing = data_train.isnull().sum()/len(data_train) +missing = missing[missing > 0] +missing.sort_values(inplace=True) +missing.plot.bar() +``` + + + + + + + + + +![output_34_1.png](https://img-blog.csdnimg.cn/20200905092323179.png) + + +了解哪些列存在 “nan”, 并可以把nan的个数打印,主要的目的在于 nan存在的个数是否真的很大,如果很小一般选择填充,如果使用lgb等树模型可以直接空缺,让树自己去优化,但如果nan存在的过多、可以考虑删掉 + +查看训练集测试集中特征属性只有一值的特征 + + +```python +one_value_fea = [col for col in data_train.columns if data_train[col].nunique() <= 1] +``` + + +```python +one_value_fea_test = [col for col in data_test_a.columns if data_test_a[col].nunique() <= 1] +``` + + +```python +one_value_fea +``` + + + + + ['policyCode'] + + + + +```python +one_value_fea_test +``` + + + + + ['policyCode'] + + + + +```python +print(f'There are {len(one_value_fea)} columns in train dataset with one unique value.') +print(f'There are {len(one_value_fea_test)} columns in test dataset with one unique value.') +``` + + There are 1 columns in train dataset with one unique value. + There are 1 columns in test dataset with one unique value. + + +### 总结: +47列数据中有22列都缺少数据,这在现实世界中很正常。‘policyCode’具有一个唯一值(或全部缺失)。有很多连续变量和一些分类变量。 + +### 2.3.5 查看特征的数值类型有哪些,对象类型有哪些 +- 特征一般都是由类别型特征和数值型特征组成 +- 类别型特征有时具有非数值关系,有时也具有数值关系。比如‘grade’中的等级A,B,C等,是否只是单纯的分类,还是A优于其他要结合业务判断。 +- 数值型特征本是可以直接入模的,但往往风控人员要对其做分箱,转化为WOE编码进而做标准评分卡等操作。从模型效果上来看,特征分箱主要是为了降低变量的复杂性,减少变量噪音对模型的影响,提高自变量和因变量的相关度。从而使模型更加稳定。 + + +```python +numerical_fea = list(data_train.select_dtypes(exclude=['object']).columns) +category_fea = list(filter(lambda x: x not in numerical_fea,list(data_train.columns))) +``` + + +```python +numerical_fea +``` + + + + + ['id', + 'loanAmnt', + 'term', + 'interestRate', + 'installment', + 'employmentTitle', + 'homeOwnership', + 'annualIncome', + 'verificationStatus', + 'isDefault', + 'purpose', + 'postCode', + 'regionCode', + 'dti', + 'delinquency_2years', + 'ficoRangeLow', + 'ficoRangeHigh', + 'openAcc', + 'pubRec', + 'pubRecBankruptcies', + 'revolBal', + 'revolUtil', + 'totalAcc', + 'initialListStatus', + 'applicationType', + 'title', + 'policyCode', + 'n0', + 'n1', + 'n2', + 'n2.1', + 'n4', + 'n5', + 'n6', + 'n7', + 'n8', + 'n9', + 'n10', + 'n11', + 'n12', + 'n13', + 'n14'] + + + + +```python +category_fea +``` + + + + + ['grade', 'subGrade', 'employmentLength', 'issueDate', 'earliesCreditLine'] + + + + +```python +data_train.grade +``` + + + + + 0 E + 1 D + 2 D + 3 A + 4 C + .. + 799995 C + 799996 A + 799997 C + 799998 A + 799999 B + Name: grade, Length: 800000, dtype: object + + + +#### 数值型变量分析,数值型肯定是包括连续型变量和离散型变量的,找出来 + +- 划分数值型变量中的连续变量和分类变量 + + +```python +#过滤数值型类别特征 +def get_numerical_serial_fea(data,feas): + numerical_serial_fea = [] + numerical_noserial_fea = [] + for fea in feas: + temp = data[fea].nunique() + if temp <= 10: + numerical_noserial_fea.append(fea) + continue + numerical_serial_fea.append(fea) + return numerical_serial_fea,numerical_noserial_fea +numerical_serial_fea,numerical_noserial_fea = get_numerical_serial_fea(data_train,numerical_fea) +``` + + +```python +numerical_serial_fea +``` + + + + + ['id', + 'loanAmnt', + 'interestRate', + 'installment', + 'employmentTitle', + 'annualIncome', + 'purpose', + 'postCode', + 'regionCode', + 'dti', + 'delinquency_2years', + 'ficoRangeLow', + 'ficoRangeHigh', + 'openAcc', + 'pubRec', + 'pubRecBankruptcies', + 'revolBal', + 'revolUtil', + 'totalAcc', + 'title', + 'n0', + 'n1', + 'n2', + 'n2.1', + 'n4', + 'n5', + 'n6', + 'n7', + 'n8', + 'n9', + 'n10', + 'n13', + 'n14'] + + + + +```python +numerical_noserial_fea +``` + + + + + ['term', + 'homeOwnership', + 'verificationStatus', + 'isDefault', + 'initialListStatus', + 'applicationType', + 'policyCode', + 'n11', + 'n12'] + + + +- 数值类别型变量分析 + + +```python +data_train['term'].value_counts()#离散型变量 +``` + + + + + 3 606902 + 5 193098 + Name: term, dtype: int64 + + + + +```python +data_train['homeOwnership'].value_counts()#离散型变量 +``` + + + + + 0 395732 + 1 317660 + 2 86309 + 3 185 + 5 81 + 4 33 + Name: homeOwnership, dtype: int64 + + + + +```python +data_train['verificationStatus'].value_counts()#离散型变量 +``` + + + + + 1 309810 + 2 248968 + 0 241222 + Name: verificationStatus, dtype: int64 + + + + +```python +data_train['initialListStatus'].value_counts()#离散型变量 +``` + + + + + 0 466438 + 1 333562 + Name: initialListStatus, dtype: int64 + + + + +```python +data_train['applicationType'].value_counts()#离散型变量 +``` + + + + + 0 784586 + 1 15414 + Name: applicationType, dtype: int64 + + + + +```python +data_train['policyCode'].value_counts()#离散型变量,无用,全部一个值 +``` + + + + + 1.0 800000 + Name: policyCode, dtype: int64 + + + + +```python +data_train['n11'].value_counts()#离散型变量,相差悬殊,用不用再分析 +``` + + + + + 0.0 729682 + 1.0 540 + 2.0 24 + 4.0 1 + 3.0 1 + Name: n11, dtype: int64 + + + + +```python +data_train['n12'].value_counts()#离散型变量,相差悬殊,用不用再分析 +``` + + + + + 0.0 757315 + 1.0 2281 + 2.0 115 + 3.0 16 + 4.0 3 + Name: n12, dtype: int64 + + + +- 数值连续型变量分析 + + +```python +#每个数字特征得分布可视化 +f = pd.melt(data_train, value_vars=numerical_serial_fea) +g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False) +g = g.map(sns.distplot, "value") +``` + + +![output_63_0.png](https://img-blog.csdnimg.cn/20200905092403482.png) + + +- 查看某一个数值型变量的分布,查看变量是否符合正态分布,如果不符合正太分布的变量可以log化后再观察下是否符合正态分布。 +- 如果想统一处理一批数据变标准化 必须把这些之前已经正态化的数据提出 + + +```python +#Ploting Transaction Amount Values Distribution +plt.figure(figsize=(16,12)) +plt.suptitle('Transaction Values Distribution', fontsize=22) +plt.subplot(221) +sub_plot_1 = sns.distplot(data_train['loanAmnt']) +sub_plot_1.set_title("loanAmnt Distribuition", fontsize=18) +sub_plot_1.set_xlabel("") +sub_plot_1.set_ylabel("Probability", fontsize=15) + +plt.subplot(222) +sub_plot_2 = sns.distplot(np.log(data_train['loanAmnt'])) +sub_plot_2.set_title("loanAmnt (Log) Distribuition", fontsize=18) +sub_plot_2.set_xlabel("") +sub_plot_2.set_ylabel("Probability", fontsize=15) +``` + + + + + Text(0, 0.5, 'Probability') + + + + +![output_65_1.png](https://img-blog.csdnimg.cn/20200905092444845.png) + + +- 非数值类别型变量分析 + + + +```python +category_fea +``` + + + + + ['grade', 'subGrade', 'employmentLength', 'issueDate', 'earliesCreditLine'] + + + + +```python +data_train['grade'].value_counts() +``` + + + + + B 233690 + C 227118 + A 139661 + D 119453 + E 55661 + F 19053 + G 5364 + Name: grade, dtype: int64 + + + + +```python +data_train['subGrade'].value_counts() +``` + + + + + C1 50763 + B4 49516 + B5 48965 + B3 48600 + C2 47068 + C3 44751 + C4 44272 + B2 44227 + B1 42382 + C5 40264 + A5 38045 + A4 30928 + D1 30538 + D2 26528 + A1 25909 + D3 23410 + A3 22655 + A2 22124 + D4 21139 + D5 17838 + E1 14064 + E2 12746 + E3 10925 + E4 9273 + E5 8653 + F1 5925 + F2 4340 + F3 3577 + F4 2859 + F5 2352 + G1 1759 + G2 1231 + G3 978 + G4 751 + G5 645 + Name: subGrade, dtype: int64 + + + + +```python +data_train['employmentLength'].value_counts() +``` + + + + + 10+ years 262753 + 2 years 72358 + < 1 year 64237 + 3 years 64152 + 1 year 52489 + 5 years 50102 + 4 years 47985 + 6 years 37254 + 8 years 36192 + 7 years 35407 + 9 years 30272 + Name: employmentLength, dtype: int64 + + + + +```python +data_train['issueDate'].value_counts() +``` + + + + + 2016-03-01 29066 + 2015-10-01 25525 + 2015-07-01 24496 + 2015-12-01 23245 + 2014-10-01 21461 + ... + 2007-08-01 23 + 2007-07-01 21 + 2008-09-01 19 + 2007-09-01 7 + 2007-06-01 1 + Name: issueDate, Length: 139, dtype: int64 + + + + +```python +data_train['earliesCreditLine'].value_counts() +``` + + + + + Aug-2001 5567 + Sep-2003 5403 + Aug-2002 5403 + Oct-2001 5258 + Aug-2000 5246 + ... + May-1960 1 + Apr-1958 1 + Feb-1960 1 + Aug-1946 1 + Mar-1958 1 + Name: earliesCreditLine, Length: 720, dtype: int64 + + + + +```python +data_train['isDefault'].value_counts() +``` + + + + + 0 640390 + 1 159610 + Name: isDefault, dtype: int64 + + + +### 总结: +- 上面我们用value_counts()等函数看了特征属性的分布,但是图表是概括原始信息最便捷的方式。 +- 数无形时少直觉。 +- 同一份数据集,在不同的尺度刻画上显示出来的图形反映的规律是不一样的。python将数据转化成图表,但结论是否正确需要由你保证。 + +### 2.3.6 变量分布可视化 + +#### 单一变量分布可视化 + + +```python +plt.figure(figsize=(8, 8)) +sns.barplot(data_train["employmentLength"].value_counts(dropna=False)[:20], + data_train["employmentLength"].value_counts(dropna=False).keys()[:20]) +plt.show() +``` + + +![output_77_0.png](https://img-blog.csdnimg.cn/20200905092517742.png) + + +#### 根绝y值不同可视化x某个特征的分布 + +- 首先查看类别型变量在不同y值上的分布 + + +```python +train_loan_fr = data_train.loc[data_train['isDefault'] == 1] +train_loan_nofr = data_train.loc[data_train['isDefault'] == 0] +``` + + +```python +fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 8)) +train_loan_fr.groupby('grade')['grade'].count().plot(kind='barh', ax=ax1, title='Count of grade fraud') +train_loan_nofr.groupby('grade')['grade'].count().plot(kind='barh', ax=ax2, title='Count of grade non-fraud') +train_loan_fr.groupby('employmentLength')['employmentLength'].count().plot(kind='barh', ax=ax3, title='Count of employmentLength fraud') +train_loan_nofr.groupby('employmentLength')['employmentLength'].count().plot(kind='barh', ax=ax4, title='Count of employmentLength non-fraud') +plt.show() +``` + + +![output_81_0.png](https://img-blog.csdnimg.cn/20200905092545400.png) + + +- 其次查看连续型变量在不同y值上的分布 + + +```python +fig, ((ax1, ax2)) = plt.subplots(1, 2, figsize=(15, 6)) +data_train.loc[data_train['isDefault'] == 1] \ + ['loanAmnt'].apply(np.log) \ + .plot(kind='hist', + bins=100, + title='Log Loan Amt - Fraud', + color='r', + xlim=(-3, 10), + ax= ax1) +data_train.loc[data_train['isDefault'] == 0] \ + ['loanAmnt'].apply(np.log) \ + .plot(kind='hist', + bins=100, + title='Log Loan Amt - Not Fraud', + color='b', + xlim=(-3, 10), + ax=ax2) +``` + + + + + + + + + +![output_83_1.png](https://img-blog.csdnimg.cn/20200905092739409.png) + + + +```python +total = len(data_train) +total_amt = data_train.groupby(['isDefault'])['loanAmnt'].sum().sum() +plt.figure(figsize=(12,5)) +plt.subplot(121)##1代表行,2代表列,所以一共有2个图,1代表此时绘制第一个图。 +plot_tr = sns.countplot(x='isDefault',data=data_train)#data_train‘isDefault’这个特征每种类别的数量** +plot_tr.set_title("Fraud Loan Distribution \n 0: good user | 1: bad user", fontsize=14) +plot_tr.set_xlabel("Is fraud by count", fontsize=16) +plot_tr.set_ylabel('Count', fontsize=16) +for p in plot_tr.patches: + height = p.get_height() + plot_tr.text(p.get_x()+p.get_width()/2., + height + 3, + '{:1.2f}%'.format(height/total*100), + ha="center", fontsize=15) + +percent_amt = (data_train.groupby(['isDefault'])['loanAmnt'].sum()) +percent_amt = percent_amt.reset_index() +plt.subplot(122) +plot_tr_2 = sns.barplot(x='isDefault', y='loanAmnt', dodge=True, data=percent_amt) +plot_tr_2.set_title("Total Amount in loanAmnt \n 0: good user | 1: bad user", fontsize=14) +plot_tr_2.set_xlabel("Is fraud by percent", fontsize=16) +plot_tr_2.set_ylabel('Total Loan Amount Scalar', fontsize=16) +for p in plot_tr_2.patches: + height = p.get_height() + plot_tr_2.text(p.get_x()+p.get_width()/2., + height + 3, + '{:1.2f}%'.format(height/total_amt * 100), + ha="center", fontsize=15) +``` + + +![output_84_0.png](https://img-blog.csdnimg.cn/20200905092816794.png) + + +### 2.3.6 时间格式数据处理及查看 + + +```python +#转化成时间格式 +data_train['issueDate'] = pd.to_datetime(data_train['issueDate'],format='%Y-%m-%d') +startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d') +data_train['issueDateDT'] = data_train['issueDate'].apply(lambda x: x-startdate).dt.days +``` + + +```python +#转化成时间格式 +data_test_a['issueDate'] = pd.to_datetime(data_train['issueDate'],format='%Y-%m-%d') +startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d') +data_test_a['issueDateDT'] = data_test_a['issueDate'].apply(lambda x: x-startdate).dt.days +``` + + +```python +plt.hist(data_train['issueDateDT'], label='train'); +plt.hist(data_test_a['issueDateDT'], label='test'); +plt.legend(); +plt.title('Distribution of issueDateDT dates'); +#train 和 test issueDateDT 日期有重叠 所以使用基于时间的分割进行验证是不明智的 +``` + + +![output_88_0.png](https://img-blog.csdnimg.cn/20200905092845328.png) + + +### 2.3.7 掌握透视图可以让我们更好的了解数据 + + +```python +#透视图 索引可以有多个,“columns(列)”是可选的,聚合函数aggfunc最后是被应用到了变量“values”中你所列举的项目上。 +pivot = pd.pivot_table(data_train, index=['grade'], columns=['issueDateDT'], values=['loanAmnt'], aggfunc=np.sum) +``` + + +```python +pivot +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
loanAmnt
issueDateDT0306192122153183214245274...3926395739874018404840794110414041714201
grade
ANaN53650.042000.019500.034425.063950.043500.0168825.085600.0101825.0...13093850.011757325.011945975.09144000.07977650.06888900.05109800.03919275.02694025.02245625.0
BNaN13000.024000.032125.07025.095750.0164300.0303175.0434425.0538450.0...16863100.017275175.016217500.011431350.08967750.07572725.04884600.04329400.03922575.03257100.0
CNaN68750.08175.010000.061800.052550.0175375.0151100.0243725.0393150.0...17502375.017471500.016111225.011973675.010184450.07765000.05354450.04552600.02870050.02246250.0
DNaNNaN5500.02850.028625.0NaN167975.0171325.0192900.0269325.0...11403075.010964150.010747675.07082050.07189625.05195700.03455175.03038500.02452375.01771750.0
E7500.0NaN10000.0NaN17975.01500.094375.0116450.042000.0139775.0...3983050.03410125.03107150.02341825.02225675.01643675.01091025.01131625.0883950.0802425.0
FNaNNaN31250.02125.0NaNNaNNaN49000.027000.043000.0...1074175.0868925.0761675.0685325.0665750.0685200.0316700.0315075.072300.0NaN
GNaNNaNNaNNaNNaNNaNNaN24625.0NaNNaN...56100.0243275.0224825.064050.0198575.0245825.053125.023750.025100.01000.0
+

7 rows × 139 columns

+
+ + + +### 2.3.8 用pandas_profiling生成数据报告 + + +```python +import pandas_profiling +``` + + +```python +pfr = pandas_profiling.ProfileReport(data_train) +pfr.to_file("./example.html") +``` + +## 2.4 总结 + +数据探索性分析是我们初步了解数据,熟悉数据为特征工程做准备的阶段,甚至很多时候EDA阶段提取出来的特征可以直接当作规则来用。可见EDA的重要性,这个阶段的主要工作还是借助于各个简单的统计量来对数据整体的了解,分析各个类型变量相互之间的关系,以及用合适的图形可视化出来直观观察。希望本节内容能给初学者带来帮助,更期待各位学习者对其中的不足提出建议。 + +END. +【 言溪:Datawhale成员,金融风控爱好者。知乎地址:https://www.zhihu.com/people/exuding】 + +关于Datawhale: + +Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale 以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时 Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + +本次数据挖掘路径学习,专题知识将在天池分享,详情可关注Datawhale: + +![logo.png](https://img-blog.csdnimg.cn/2020090509294089.png) + +