探索性数据分析(EDA)
目的
- 了解数据的属性类型和缺失情况
- 分析特征和预测标签的关系便于进一步了解如何构建特征工程
- 了解变量间的相互关系、变量与预测值之间的存在关系。
内容介绍
- 特征数据类型以及缺失值分析
- 数据总体的描述以及异常分析
- 连续特征的分布以及离散特征的字段数分析
- 特征与label的分析
一、特征数据类型以及缺失值分析
首先导入必要的包
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
接着我们读取数据可以看看数据的大小
train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('testA.csv')
print('train_data的大小为{},test_data的大小为{}'.format(train_data.shape,
test_data.shape))
使用info()函数查看数据的大小以及数据类型
train_data.info()
可以看出有不少object变量,之后特征工程需要处理并编码这些特征。
缺失值分析:
#缺失值分析
print(train_data.isnull().sum()/(len(train_data)))
针对以上缺失数据,我们大概有几种常见的做法。
- 插值算法填充(朗格朗日插值,KNN等)
- 统计数填充(均值,中位数,众数等填充)
- 留给后面的树模型(lgb,xgb)自动填充
那肯定是第三钟香!
进一步我们可以可视化该缺失值
首先需要安装一个包:missingno
pip install missingno --user
#缺失值可视化
import missingno as msno
msno.matrix(train_data)
二、数据总体的描述以及异常分析
使用describe()函数进一步观察数据。
train_data.describe()
观察表后可以看出一些端倪。比如说,其中installment和enploymenTitle中的最大值比3/4分位数大了很多。可以结合特征的含义分析其是否异常。为了进一步观察特征的异常值。我们可以采用如下做法。
train_data.describe(percentiles = np.array(list(range(10))) * 0.1 )
这样的话可以更加细致的看数据的异常。可以观察后面的列是否有负数,最大值合不合理等等。
三、连续特征的分布以及离散特征的字段数分析
import seaborn as sns
f = pd.melt(train_data, value_vars=con_col)
g = sns.FacetGrid(f, col="variable", col_wrap=4, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")
对于偏态的数据我们可以做log,box-cox变换等操作使它趋向高斯分布,从而让模型收敛以及泛化性越高。接着对类别变量分析:
#类别变量分析
# pd.DataFrame(train_data[set(lei_col.tolist()+obj_col.tolist())])
for col in set(lei_col.tolist()+obj_col.tolist()):
print(train_data[col].value_counts(normalize=True))
#n12,policyCode,n11可以删,pubRecBankruptcies分箱
看看类别是否存在严重不均衡的情况,若有,该特征意义不大。可以剔除。
3.1 双变量分析
import matplotlib.pyplot as plt
import seaborn as sns
fig = plt.figure(figsize = (18,18))
for col,i in zip(con_col,range(1,31)):
plt.subplot(6,5,i)
sns.boxplot(x='isDefault', y=col, data=train_data)
以上给出部分的图,从箱型图中,由于有些特征长尾分布异常值过高,只能看出postcode regioncode n6 n8考虑删去,另外可以看出interestRate是相对不错的特征。
3.2 类别特征与标签的关系
# train_data.groupby()
import seaborn as sns
import matplotlib.pyplot as plt
fig = plt.figure(figsize = (18,18))
analyse1_col = list(set(lei_col.tolist()+obj_col.tolist()))
#由于我们删除了n11 n12 policyCode
new_drop = drop_col + drop_col2
for drop in new_drop:
if drop in analyse1_col:
analyse1_col.remove(drop)
else:
pass
for col,i in zip(analyse1_col,range(1,len(analyse1_col)+1)):
plt.subplot(5,3,i)
sns.countplot(x=col, hue='isDefault' , data=train_data);
applicationType,initialListStatus,grade,verificationSatus,subGradeq区分度蛮大,特征较不错