EDA是建模之前非常重要的部分,可以查看数据的具体情况,探究一下变量的类型,为建模框架做准备。
1. 查看缺失值
# pd.dataframe.any() axis=0,是否列所有取值为True;axis=1;是否index的所有取值为True
# f-string 格式化字符串,{}内为被替换的内容
print(f'There are {train.isnull().any().sum()} columns in training set with missing values')
# 检查哪些变量具体缺失率
for col in train.columns:
print(col, str(round(train[col].isnull().sum()/train.shape[0]*100,2)),'%')
miss_rate = train.isnull().sum()/train.shape[0]
# 使用pandas中的sort_values排序
miss_rate.sort_values(ascending=False, inplace=True)
miss_rate.plot.bar()
缺失情况都不算严重,可以通过插值来解决。
2.变量检测
# 检查变量只有一个取值的情况
sig_value_col = [col for col in train.columns if train[col].nunique()==1]
print(sig_value_col)
sig_value_col_testA = [col for col in testA.columns if testA[col].nunique()==1]
sig_value_col_testA
policyCode变量只有一种取值,之后建模可以不考虑。
# DataFrame的select_dtypes方法返回具有指定数据类型的列。
num_fea = list(train.select_dtypes(exclude='object').columns)
cat_fea = [i for i in list(train.columns) if i not in num_fea]
## 其中,数值型变量也包括离散变量,需要找出来
# 将取值小于10个的看做类别变量
cat_num_fea = []
numerical_fea = []
for fea in num_fea:
num_range = train[fea].nunique()
if num_range <= 10:
cat_num_fea.append(fea)
continue
numerical_fea.append(fea)
# 查看变量类型情况
print('分类变量:', cat_fea)
print('数值型分类变量', cat_num_fea)
print('数值型连续变量', numerical_fea)
根据原数据的类型(文本与数值型)初步分出分类变量和数值型变量。其中数值型又包含连续变量和经过编码后的分类变量,这个根据分类数初步作区分,然后根据结果手动调整。
# 修改分类情况
cat_num_fea.remove('isDefault')
cat_num_fea.remove(sig_value_col[0])
numerical_fea.remove('id')
# 出现误分情况
err_fea = ['employmentTitle','purpose','postCode','regionCode','title'] # 类别取值个数>10
date_fea = ['earliesCreditLine','issueDate'] # 日期类型数据
numerical_fea = [col for col in numerical_fea if col not in err_fea ]
cat_fea = [col for col in cat_fea if col not in date_fea]
# 统计err_fea的取值情况
for col in err_fea:
print(col,':\n')
print('取值个数为:',train[col].nunique())
print('\n取值统计:\n',train[col].value_counts())
# purpose共14个取值,可用
# 其他类别变量需要进一步合并
3. 变量取值与变量间关系可视化
对于连续型变量:
hist频率分布直方图或者density密度图
对于离散型:
barplot柱状图
对于变量间的关系:
热度矩阵图plt.matshow()–连续vs连续
箱线图boxplot–离散vs连续
散点图or散点图矩阵:连续x vs. 连续y/x
3.1 连续数值型变量
# 分布直方图
f = pd.melt(train, value_vars=numerical_fea)
import seaborn as sns
g = sns.FacetGrid(f, col='variable',
col_wrap=3, # col_wrap:画布列的个数
sharex=False, sharey=False) # 画轮廓
g = g.map(sns.distplot, 'value')
# 检查是否符合正态分布,右偏太严重考虑对数变换
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
# 连续变量和y之间的关系
plt.figure(figsize=(20,8))
plt.subplot(121)
train_fa['loanAmnt'].apply(np.log).plot(kind='hist',
bins=100,
title='Log Loan Amount-Default',
color='red')
plt.subplot(122)
train_nofa['loanAmnt'].apply(np.log).plot(kind='hist',
bins=100,
title='Log Loan Amount-Not Default',
color='blue')
# 变量间相关关系
plt.figure(figsize=(20,20))
plt.matshow(train[numerical_fea].corr(), fignum=0)
plt.xticks(range(len(numerical_fea)), numerical_fea, rotation=45, fontsize=14)
plt.yticks(range(len(numerical_fea)), numerical_fea, fontsize=14)
cb = plt.colorbar()
cb.ax.tick_params(labelsize=14)
3.2 离散变量
fig,ax = plt.subplots(2,4, figsize=(40,20))
ax = ax.flatten()
for i in range(7):
axe = ax[i]
fea = cat_num_fea[i]
sns.barplot(train[fea].value_counts(dropna=False).keys(),
train[fea].value_counts(dropna=False),
ax=axe)
plt.show()
fig,ax = plt.subplots(1,3, figsize=(30,10))
ax = ax.flatten()
for i in range(3):
axe = ax[i]
fea = cat_fea[i]
sns.barplot(train[fea].value_counts(dropna=False),
train[fea].value_counts(dropna=False).keys(),
ax=axe)
plt.show()
# 类别变量在不同y上的分布
train_fa = train.loc[train['isDefault']==1]
train_nofa = train.loc[train['isDefault']==0]
plt.figure(figsize=(20,10))
plt.subplot(1,2,1)
sns.barplot(train_fa['grade'].value_counts(dropna=False),
train_fa['grade'].value_counts(dropna=False).keys())
plt.title('barplot of grades of default people', fontsize=20)
plt.subplot(1,2,2)
sns.barplot(train_nofa['grade'].value_counts(dropna=False),
train_nofa['grade'].value_counts(dropna=False).keys())
plt.title('barplot of grades of not default people', fontsize=20)
plt.show()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
plt.figure(figsize=(20,10))
plt.subplot(1,2,1)
sns.barplot(train_fa['employmentLength'].value_counts(dropna=False),
train_fa['employmentLength'].value_counts(dropna=False).keys())
plt.title('barplot of employmentLength of default people', fontsize=20)
plt.subplot(1,2,2)
sns.barplot(train_nofa['employmentLength'].value_counts(dropna=False),
train_nofa['employmentLength'].value_counts(dropna=False).keys())
plt.title('barplot of employmentLength of not default people', fontsize=20)
plt.show()