金融风控训练营EDA探索性数据分析学习笔记

本文介绍了数据探索分析的步骤,包括数据集的大小、特征类型、统计量、缺失值分析和唯一值检查。通过`pandas`库进行数据读取和初步分析,发现训练集中有22列存在缺失值,但无特征的缺失率超过50%。同时,'policyCode'特征具有唯一值,'applicationType'、'n11'和'n12'的取值分布不均。此外,还探讨了数值型和类别型特征的分布,并展示了如何生成数据报告。
摘要由CSDN通过智能技术生成

一、学习知识点概要

  • 数据总体了解

    • 读取数据集并了解数据集大小,原始特征维度;
    • 通过info熟悉数据类型;
    • 粗略查看数据集中各特征基本统计量;
  • 数据质量分析
    • 查看数据缺失值情况
    • 查看唯一值特征情况
  • 深入分析数据类型
    • 类别型数据
    • 数值型数据
      • 离散数值型数据
      • 连续数值型数据
  • 数据间相关关系
    • 特征和特征之间关系
    • 特征和目标变量之间关系
  • 用pandas_profiling生成数据报告

二、学习内容

2.1 数据总体了解

  • 读取数据集并了解数据集大小,原始特征维度;
  • 通过info熟悉数据类型;
  • 粗略查看数据集中各特征基本统计量;

2.1.1 数据集大小

  • 本次数据集下载文件格式为csv格式,读取文件可采用如下方法:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import datetime

train=pd.read_csv('C://Users//Administrator//Desktop//train.csv')
testA=pd.read_csv('C://Users//Administrator//Desktop//testA.csv')
  • 查看数据集大小和原始特征维度
print(train.columns) #训练集样本属性
print("训练集样本维度:",train.shape)   #训练集样本维度
print("测试集A样本维度:",testA.shape)   #测试集A样本维度

输出结果如下:

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', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8',
       'n9', 'n10', 'n11', 'n12', 'n13', 'n14'],
      dtype='object')
训练集样本维度: (800000, 47)
测试集A样本维度: (200000, 46)

2.1.2 数据类型

train.info()   #查看数据类型
输出结果如下:
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  datetime64[ns]
 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  n3                  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: datetime64[ns](1), float64(33), int64(9), object(4)
memory usage: 293.0+ MB

2.1.3 基本统计量

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

2.2 数据质量分析

2.2.1 缺失值

  • 查看缺失值基本代码
train.isnull()   ##查看数据集中各元素是否存在缺失值,存在则返回True,不存在则返回False
train.isnull().any()   ##查看各列是否存在缺失值,存在则返回True,不存在则返回False

train.isnull().any().sum()  ##存在缺失值的列数
train.isnull().sum() ##各列缺失值的个数

missing = train.columns[ train.isnull().any() ].tolist()  ##存在缺失值的列名
train [ missing ].isnull().sum()  ##存在缺失值的列及其对应缺失值的个数
  • 缺失值分析
num_miss=train.isnull().any().sum()  ##存在缺失值的列数
print("训练集中有",num_miss,"列存在缺失值.")

missing = train.columns[ train.isnull().any() ].tolist()  ##存在缺失值的列名
train [ missing ].isnull().sum()  ##存在缺失值的各列中缺失值的个数
训练集中有 22 列存在缺失值.
employmentTitle           1
employmentLength      46799
postCode                  1
dti                     239
pubRecBankruptcies      405
revolUtil               531
title                     1
n0                    40270
n1                    40270
n2                    40270
n3                    40270
n4                    33239
n5                    40270
n6                    40270
n7                    40270
n8                    40271
n9                    40270
n10                   33239
n11                   69752
n12                   40270
n13                   40270
n14                   40270
dtype: int64

从上面的结果我们可以看到,训练集中有22列特征存在缺失值以及这些列中存在的缺失值个数,接下来则具体分析各列特征的缺失率,对于某列特征,若其缺失率过高,则其对于目标特征的基本没有太大影响,可以考虑删除该列,但如果缺失值较小一般选择填充。下面进一步查看存在缺失值的各列中缺失率大于50%的特征。

have_null_fea_dict = (train.isnull().sum()/len(train)).to_dict()
fea_null_moreThanHalf = {}
for key,value in have_null_fea_dict.items():
    if value > 0.5:
        fea_null_moreThanHalf[key] = value
fea_null_moreThanHalf

输出结果如下:

{ }

由此可见,该训练集中不存在缺失率大于50%的特征,我们可以作图可视化对比各列特征的缺失率

train [ missing ].isnull().sum().sort_values(inplace=True)
train [ missing ].isnull().sum().plot.bar()

输入结果如下:

2.2.2 唯一值

one_value_fea = [col for col in train.columns if train[col].nunique() <= 1]
one_value_fea_testA = [col for col in testA.columns if testA[col].nunique() <= 1]
print("训练集中唯一值特征:",one_value_fea)
print("测试集A中唯一值特征:",one_value_fea_testA)

输出结果如下:

训练集中唯一值特征: ['policyCode']
测试集A中唯一值特征: ['policyCode']

从输出结果可以看到,数据集中'policyCode'这一列具有一个唯一值(或全部缺失)

2.3 深入分析数据类型

特征一般分为数值型(连续型、离散性)特征和类别型特征,从2.1.2查看数据类型我们已经得到了训练集中涉及到的数据类型种类及个数:float64(33), int64(9), object(5),为进一步清晰了解哪些特征属于数值型,哪些特征属于类别型,可经过如下命令查看:

numerical_fea = list(train.select_dtypes(exclude=['object']).columns)
category_fea = list(filter(lambda x: x not in numerical_fea,list(train.columns)))
print("数值型特征:\n",numerical_fea)
print("类别型特征:\n",category_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', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12', 'n13', 'n14']
类别型特征:
 ['grade', 'subGrade', 'employmentLength', 'issueDate', 'earliesCreditLine']

对于数值型特征又分为离散性和连续型,若定义特征中的数值不超过10个视为离散型,则可以通过以下代码区分开来:

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(train,numerical_fea)

print("连续型特征:\n",numerical_serial_fea)
print("离散型特征:\n",numerical_noserial_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', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n13', 'n14']
离散型特征:
 ['term', 'homeOwnership', 'verificationStatus', 'isDefault', 'initialListStatus', 'applicationType', 'policyCode', 'n11', 'n12']

2.3.1 类别型特征分析

通过train['列名'].value_counts()可以统计类别型特征的取值及其个数,结果如下表所示:

(上图只是通过代码得到的结果整理而成的表格,对于少量数据而言还能看得过去,但对于大量数据可行性不强,下面进行图表可视化对比更加直观)

##以类别型变量'grade'为例
plt.figure(figsize=(6, 6))
sns.barplot(train["grade"].value_counts(dropna=False)[:20],
            train["grade"].value_counts(dropna=False).keys()[:20])
plt.show()

             

2.3.2 数值离散型特征分析

通过train['列名'].value_counts()可以统计离散型数值特征的取值及其个数,结果如下表所示:

(上图只是通过代码得到的结果整理而成的表格,对于少量数据而言还能看得过去,但对于大量数据可行性不强,下面进行图表可视化对比更加直观)

                       

从上述结果可以作初步判断,'policyCode'存在唯一值1.0,可视为无用特征;'applicationType'、'n11'和'n12'各取值相差悬殊,后面应对其进行分析考虑是否有影响。

2.3.3 数值连续型特征分析

##得到每个连续型特征的分布直方图
f = pd.melt(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")

查看某一个数值型变量的分布,查看变量是否符合正态分布,如果不符合正太分布的变量可以log化后再观察下是否符合正态分布。

如果想统一处理一批数据变标准化 必须把这些之前已经正态化的数据提出。

正态化的原因:一些情况下正态非正态可以让模型更快的收敛,一些模型要求数据正态(eg. GMM、KNN),保证数据不要过偏态即可,过于偏态可能会影响模型预测结果。

2.4 相关性分析

2.4.1 查看各特征不同标签(isDefault)下分布情况  

  • 类别型(离散型)
train_loan_fr = train.loc[train['isDefault'] == 1]
train_loan_nofr = train.loc[train['isDefault'] == 0]

fig, ((ax1, ax2), (ax3, ax4),(ax5, ax6),(ax7, ax8),(ax9, ax10)) = plt.subplots(5, 2, figsize=(15, 30))
train_loan_fr.groupby('grade')['grade'].count()[:20].plot(kind='barh', ax=ax1, title='Count of grade fraud')
train_loan_nofr.groupby('grade')['grade'].count()[:20].plot(kind='barh', ax=ax2, title='Count of grade non-fraud')

train_loan_fr.groupby('subGrade')['subGrade'].count()[:20].plot(kind='barh', ax=ax3, title='Count of subGrade fraud')
train_loan_nofr.groupby('subGrade')['subGrade'].count()[:20].plot(kind='barh', ax=ax4, title='Count of subGrade non-fraud')

train_loan_fr.groupby('employmentLength')['employmentLength'].count()[:20].plot(kind='barh', ax=ax5, title='Count of employmentLength fraud')
train_loan_nofr.groupby('employmentLength')['employmentLength'].count()[:20].plot(kind='barh', ax=ax6, title='Count of employmentLength non-fraud')

train_loan_fr.groupby('issueDate')['issueDate'].count()[:20].plot(kind='barh', ax=ax7, title='Count of issueDate fraud')
train_loan_nofr.groupby('issueDate')['issueDate'].count()[:20].plot(kind='barh', ax=ax8, title='Count of issueDate non-fraud')

train_loan_fr.groupby('earliesCreditLine')['earliesCreditLine'].count()[:20].plot(kind='barh', ax=ax9, title='Count of earliesCreditLine fraud')
train_loan_nofr.groupby('earliesCreditLine')['earliesCreditLine'].count()[:20].plot(kind='barh', ax=ax10, title='Count of earliesCreditLine non-fraud')

plt.show()

  • 连续型
fig, ((ax1, ax2)) = plt.subplots(1, 2, figsize=(15, 6))
train.loc[train['isDefault'] == 1]['loanAmnt'].apply(np.log).plot(kind='hist',bins=100,title='Log Loan Amt - Fraud',color='r',xlim=(-3, 10),ax= ax1)
train.loc[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)

2.4.2 时间格式处理

#转化成时间格式  issueDateDT特征表示数据日期离数据集中日期最早的日期(2007-06-01)的天数
train['issueDate'] = pd.to_datetime(train['issueDate'],format='%Y-%m-%d')
startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d')
train['issueDateDT'] = train['issueDate'].apply(lambda x: x-startdate).dt.days

#转化成时间格式
testA['issueDate'] = pd.to_datetime(train['issueDate'],format='%Y-%m-%d')
startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d')
testA['issueDateDT'] = testA['issueDate'].apply(lambda x: x-startdate).dt.days

plt.hist(train['issueDateDT'], label='train');
plt.hist(testA['issueDateDT'], label='test');
plt.legend();
plt.title('Distribution of issueDateDT dates');

从图示我们可以看到,train 和 testA的issueDate日期有重叠,所以使用基于时间的分割进行验证是不明智的。

2.5 生成数据报告

Python之pandas-profiling:pandas-profiling库的简介、安装、使用方法之详细攻略

import pandas_profiling
pfr = pandas_profiling.ProfileReport(train)
pfr.to_file("./example.html")

三、学习问题与解答

3.1 各种类型文件的读取

import pandas as pd
dataframe=pd.read_csv('文件名.csv')
  • Excel文件
import pandas as pd
dataframe=pd.read_excel('文件名.xlsx')
  • SQL文件:在读取mysql数据之前要将mysql的服务启动-net start mysql

import pymysql
import pandas as pd
#连接数据库为test,用户名为root,密码是123456(根据自己的数据库信息输入)
conn=pymysql.connect(host="127.0.0.1",user="root",passwd="123456",db="test")
#查询的表为students
sql="select * from students"
data=pd.read_sql(sql,conn)
print(data)
  • HTML文件:
import pandas as pd
htl=pd.read_html('地址.html')
print(htl)

3.2 正态分布的基本原理

可参考此文章:数据的正态化和标准变换

四、学习思考与总结

本次学习任务了解了探索性数据分析的基本步骤,从读取数据、初步查看数据、深入了解数据、观察特征之间的相关性以及特征与标签的相关性,而这些信息均可通过可视化图表来直观获取,探索性数据分析只是对数据进行一个大体的了解,为之后的进一步分析打下基础,是数据分析中比较重要的一个环节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值