目录
探索性数据分析
探索性数据分析(Exploratory Data Analysis,EDA)是指对已有数据在尽量少的先验假设下通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。在我们队一个项目制定的以及实施的过程中有什么疑问性的问题,我们都可以做一个探索性数据分析来明晰我们的思路。
EDA目标
- 对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律。
- 了解变量间的相互关系以及变量与预测值之间的存在关系。
- 引导数据科学从业者进行数据处理以及特征工程的步骤,使数据集的结构和特征集让接下来的预测问题更加可靠。
项目介绍
预测二手车交易价格
- 载入数据科学以及可视化库
- 载入数据
- 数据处理
- 了解预测值分布
- 特征分析
- 生成数据报告
具体实现
根据个部分的内容通过代码实现一下思路
1.导入相关包
# 基础数据科学工具以及可视化等
import numpy as np
import pandas as pd
import warnings
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.special import jn
from IPython.display import display, clear_output
import time
warnings.filterwarnings('ignore')
%matplotlib inline
#模型预测的
from sklearn import linear_model
from sklearn import preprocessing
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor
#数据降维处理的
from sklearn.decomposition import PCA,FastICA,FactorAnalysis,SparsePCA
import lightgbm as lgb
import xgboost as xgb
#参数搜索和评价的
from sklearn.model_selection import GridSearchCV,cross_val_score,StratifiedKFold,train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error
包的安装一般用pip 安装就可以,多版本的时候用python3就使用pip3用于区分
pip install ***
pip3 install ***
2.载入数据
数据下载链接:
链接:https://pan.baidu.com/s/1qHPUtXBfWMa_qLoExJ94GA
提取码:idey
## 通过Pandas对于数据进行读取 (pandas是一个很友好的数据读取函数库)
f1=open('C:/Users/zxy/Desktop/数据挖掘/data/used_car_train_20200313-1.csv')
f2=open('C:/Users/zxy/Desktop/数据挖掘/data/used_car_train_20200313-1.csv')
Train_data = pd.read_csv(f1,encoding='gbk')
TestA_data = pd.read_csv(f2,encoding='gbk')
## 输出数据的大小信息
print('Train data shape:',Train_data.shape)
print('TestA data shape:',TestA_data.shape)
注:打开数据的时候,路径如果包含中文名称,直接用pd.csv()打开会出现报错。直接用open()打开,就不会有这种情况,或者直接用英文路径。
3.数据简要浏览
## 通过.head() 简要浏览读取数据的形式
Train_data.head(10)
out:
SaleID | name | regDate | model | brand | bodyType | fuelType | gearbox | power | kilometer | notRepairedDamage | regionCode | seller | offerType | creatDate | price | v_0 | v_1 | … | v_14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 736 | 20040402 | 30 | 6 | 1 | 0 | 0 | 60 | 12.5 | 0 | 1046 | 0 | 0 | 20160404 | 1850 | 43.35779631 | 3.966344166 | … | 0.9147625 |
1 | 2262 | 20030301 | 40 | 1 | 2 | 0 | 0 | 0 | 15 | - | 4366 | 0 | 0 | 20160309 | 3600 | 45.30527302 | 5.236111898 | … | 0.245522411 |
2 | 14874 | 20040403 | 115 | 15 | 1 | 0 | 0 | 163 | 12.5 | 0 | 2806 | 0 | 0 | 20160402 | 6222 | 45.97835906 | 4.823792215 | … | -0.229962856 |
3 | 71865 | 19960908 | 109 | 10 | 0 | 0 | 1 | 193 | 15 | 0 | 434 | 0 | 0 | 20160312 | 2400 | 45.6874782 | 4.492574134 | … | -0.478699379 |
4 | 111080 | 20120103 | 110 | 5 | 1 | 0 | 0 | 68 | 5 | 0 | 6977 | 0 | 0 | 20160313 | 5200 | 44.38351084 | 2.031433258 | … | 1.923481963 |
5 | 137642 | 20090602 | 24 | 10 | 0 | 1 | 0 | 109 | 10 | 0 | 3690 | 0 | 0 | 20160319 | 8000 | 46.32316538 | -3.229285171 | … | 0.206572584 |
6 | 2402 | 19990411 | 13 | 4 | 0 | 0 | 1 | 150 | 15 | 0 | 3073 | 0 | 0 | 20160317 | 3500 | 46.10433462 | 4.926219444 | … | -0.103180362 |
7 | 165346 | 19990706 | 26 | 14 | 1 | 0 | 0 | 101 | 15 | 0 | 4000 | 0 | 0 | 20160326 | 1000 | 42.25558582 | -3.167771424 | … | 0.195567451 |
8 | 2974 | 20030205 | 19 | 1 | 2 | 1 | 1 | 179 | 15 | 0 | 4679 | 0 | 0 | 20160326 | 2850 | 46.08488801 | 4.89371655 | … | 0.069432964 |
9 | 82021 | 19980101 | 7 | 7 | 5 | 0 | 0 | 88 | 15 | 0 | 302 | 0 | 0 | 20160402 | 650 | 43.07462648 | 1.666386196 | … | -1.025822481 |
10 | 18961 | 20050811 | 19 | 9 | 3 | 1 | 0 | 101 | 15 | 0 | 1193 | 0 | 0 | 20160320 | 3100 | 45.40124081 | 4.195311171 | … | 0.349187337 |
3.1数据描述
describe种有每列的统计量,个数count、平均值mean、方差std、最小值min、中位数25% 50% 75% 、以及最大值 看这个信息主要是瞬间掌握数据的大概的范围以及每个值的异常值的判断,比如有的时候会发现999 9999 -1 等值这些其实都是nan的另外一种表达方式,有的时候需要注意下
Train_data.describe()
out:
SaleID | name | regDate | model | brand | bodyType | fuelType | regionCode | seller | offerType | ... | v_5 | v_6 | v_7 | v_8 | v_9 | v_10 | v_11 | v_12 | v_13 | v_14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 150000 | 150000 | 1.50E+05 | 150000 | 150000 | 150000 | 150000 | 1.50E+05 | 1.50E+05 | 1.50E+05 | ... | 150000 | 150000 | 150000 | 150000 | 150000 | 150000 | 150000 | 148531 | 146417 |
mean | 74999.5 | 68349.17287 | 2.00E+07 | 47.128953 | 8.052527 | 1.870747 | 1.394827 | 2.00E+05 | 2.84E+05 | 1.42E+06 | ... | 0.246643 | 0.062381 | 0.174574 | 0.29692 | 0.406928 | -0.164371 | -0.446352 | -0.085471 | 0.02219 |
std | 43301.41453 | 61103.8751 | 5.36E+04 | 49.535881 | 7.864603 | 5.221312 | 15.676749 | 1.99E+06 | 2.38E+06 | 5.15E+06 | ... | 0.116636 | 0.133581 | 0.927042 | 1.773396 | 1.962003 | 3.758661 | 2.00293 | 2.25773 | 1.26714 |
min | 0 | 0 | 1.99E+07 | 0 | 0 | 0 | 0 | 0.00E+00 | 0.00E+00 | 0.00E+00 | ... | 0 | 0 | -0.27351 | -8.206004 | -8.399672 | -9.168192 | -9.404106 | -9.639552 | -6.113291 |
25% | 37499.75 | 11156 | 2.00E+07 | 10 | 1 | 0 | 0 | 7.39E+02 | 0.00E+00 | 0.00E+00 | ... | 0.241064 | 0.000161 | 0.055272 | 0.03605 | 0.035225 | -3.666042 | -2.026105 | -1.745234 | -0.999703 |
50% | 74999.5 | 51638 | 2.00E+07 | 30 | 6 | 1 | 0 | 2.01E+03 | 0.00E+00 | 0.00E+00 | ... | 0.256928 | 0.001547 | 0.090081 | 0.058523 | 0.063335 | 1.240603 | -0.457218 | -0.160305 | 0.008602 |
75% | 112499.25 | 118841.25 | 2.01E+07 | 66 | 13 | 3 | 1 | 3.72E+03 | 0.00E+00 | 0.00E+00 | ... | 0.26517 | 0.104255 | 0.12059 | 0.081996 | 0.094738 | 2.691063 | 1.115744 | 1.57213 | 0.929041 |
max | 149999 | 196812 | 2.02E+07 | 247 | 39 | 999 | 3500 | 2.02E+07 | 2.02E+07 | 2.02E+07 | ... | 1.401999 | 1.387847 | 12.357011 | 18.819042 | 18.801218 | 18.802072 | 13.562011 | 11.147669 | 8.658418 |
TestA_data.describe()
out:
SaleID | name | regDate | model | brand | bodyType | fuelType | regionCode | seller | offerType | ... | v_5 | v_6 | v_7 | v_8 | v_9 | v_10 | v_11 | v_12 | v_13 | v_14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 150000.000000 | 150000.000000 | 1.500000e+05 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 1.500000e+05 | 1.500000e+05 | 1.500000e+05 | ... | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 148531.000000 | 146417.000000 |
mean | 74999.500000 | 68349.172873 | 2.003417e+07 | 47.128953 | 8.052527 | 1.870747 | 1.394827 | 1.997783e+05 | 2.841478e+05 | 1.415701e+06 | ... | 0.246643 | 0.062381 | 0.174574 | 0.296920 | 0.406928 | -0.164371 | -0.446352 | -0.085471 | 0.022190 |
std | 43301.414527 | 61103.875095 | 5.364988e+04 | 49.535881 | 7.864603 | 5.221312 | 15.676749 | 1.985073e+06 | 2.376421e+06 | 5.151321e+06 | ... | 0.116636 | 0.133581 | 0.927042 | 1.773396 | 1.962003 | 3.758661 | 2.002930 | 2.257730 | 1.267140 |
min | 0.000000 | 0.000000 | 1.991000e+07 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | ... | 0.000000 | 0.000000 | -0.273510 | -8.206004 | -8.399672 | -9.168192 | -9.404106 | -9.639552 | -6.113291 |
25% | 37499.750000 | 11156.000000 | 1.999091e+07 | 10.000000 | 1.000000 | 0.000000 | 0.000000 | 7.390000e+02 | 0.000000e+00 | 0.000000e+00 | ... | 0.241064 | 0.000161 | 0.055272 | 0.036050 | 0.035225 | -3.666042 | -2.026105 | -1.745234 | -0.999703 |
50% | 74999.500000 | 51638.000000 | 2.003091e+07 | 30.000000 | 6.000000 | 1.000000 | 0.000000 | 2.010000e+03 | 0.000000e+00 | 0.000000e+00 | ... | 0.256928 | 0.001547 | 0.090081 | 0.058523 | 0.063335 | 1.240603 | -0.457218 | -0.160305 | 0.008602 |
75% | 112499.250000 | 118841.250000 | 2.007111e+07 | 66.000000 | 13.000000 | 3.000000 | 1.000000 | 3.719000e+03 | 0.000000e+00 | 0.000000e+00 | ... | 0.265170 | 0.104255 | 0.120590 | 0.081996 | 0.094738 | 2.691063 | 1.115744 | 1.572130 | 0.929041 |
max | 149999.000000 | 196812.000000 | 2.015121e+07 | 247.000000 | 39.000000 | 999.000000 | 3500.000000 | 2.016041e+07 | 2.016041e+07 | 2.016041e+07 | ... | 1.401999 | 1.387847 | 12.357011 | 18.819042 | 18.801218 | 18.802072 | 13.562011 | 11.147669 | 8.658418 |
3.2数据信息查看
info 通过info来了解数据每列的type,有助于了解是否存在除了nan以外的特殊符号异常。
## 通过 .info() 简要可以看到对应一些数据列名,以及NAN缺失信息
Train_data.info()
out:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 31 columns):
SaleID 150000 non-null int64
name 150000 non-null int64
regDate 150000 non-null int64
model 150000 non-null int64
brand 150000 non-null int64
bodyType 150000 non-null int64
fuelType 150000 non-null float64
gearbox 150000 non-null object
power 150000 non-null object
kilometer 150000 non-null object
notRepairedDamage 150000 non-null object
regionCode 150000 non-null int64
seller 150000 non-null int64
offerType 150000 non-null float64
creatDate 150000 non-null float64
price 150000 non-null float64
v_0 150000 non-null float64
v_1 150000 non-null float64
v_2 150000 non-null float64
v_3 150000 non-null float64
v_4 150000 non-null float64
v_5 150000 non-null float64
v_6 150000 non-null float64
v_7 150000 non-null float64
v_8 150000 non-null float64
v_9 150000 non-null float64
v_10 150000 non-null float64
v_11 150000 non-null float64
v_12 148531 non-null float64
v_13 146417 non-null float64
v_14 135884 non-null float64
dtypes: float64(19), int64(8), object(4)
memory usage: 35.5+ MB
Train_data.isnull().sum()
out:
SaleID 0
name 0
regDate 0
model 0
brand 0
bodyType 0
fuelType 0
gearbox 0
power 0
kilometer 0
notRepairedDamage 0
regionCode 0
seller 0
offerType 0
creatDate 0
price 0
v_0 0
v_1 0
v_2 0
v_3 0
v_4 0
v_5 0
v_6 0
v_7 0
v_8 0
v_9 0
v_10 0
v_11 0
v_12 1469
v_13 3583
v_14 14116
dtype: int64
TestA_data.isnull().sum()
out:
SaleID 0
name 0
regDate 0
model 0
brand 0
bodyType 0
fuelType 0
gearbox 0
power 0
kilometer 0
notRepairedDamage 0
regionCode 0
seller 0
offerType 0
creatDate 0
price 0
v_0 0
v_1 0
v_2 0
v_3 0
v_4 0
v_5 0
v_6 0
v_7 0
v_8 0
v_9 0
v_10 0
v_11 0
v_12 1469
v_13 3583
v_14 14116
dtype: int64
nan可视化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
out:
通过以上两句可以很直观的了解哪些列存在 “nan”, 并可以把nan的个数打印,主要的目的在于 nan存在的个数是否真的很大,如果很小一般选择填充,如果使用lgb等树模型可以直接空缺,让树自己去优化,但如果nan存在的过多、可以考虑删掉。
缺省值信息查看
msno.matrix(Train_data.sample(250))
out:
<matplotlib.axes._subplots.AxesSubplot at 0x247481e7bc8>
msno.bar(Train_data.sample(1000))
out:
<matplotlib.axes._subplots.AxesSubplot at 0x24747ffbd88>
msno.matrix(TestA_data.sample(250))
out:
<matplotlib.axes._subplots.AxesSubplot at 0x2474ac862c8>
测试集的缺省和训练集的差不多情况, 可视化有四列有缺省,notRepairedDamage缺省得最多。
Train_data['notRepairedDamage'].value_counts()
out:
0 109301
- 17558
1 12611
70 56
486 55
...
6736 1
4370 1
6220 1
29 1
6192 1
Name: notRepairedDamage, Length: 4272, dtype: int64
TestA_data['notRepairedDamage'].value_counts()
out:
0 109301
- 17558
1 12611
70 56
486 55
...
6736 1
4370 1
6220 1
29 1
6192 1
Name: notRepairedDamage, Length: 4272, dtype: int64
了解数据分布情况
import scipy.stats as st
y = Train_data['price']
plt.figure(1); plt.title('Johnson SU')
sns.distplot(y, kde=False, fit=st.johnsonsu)
plt.figure(2); plt.title('Normal')
sns.distplot(y, kde=False, fit=st.norm)
plt.figure(3); plt.title('Log Normal')
sns.distplot(y, kde=False, fit=st.lognorm)
out:
<matplotlib.axes._subplots.AxesSubplot at 0x2474b502648>
价格不服从正态分布,所以在进行回归之前,它必须进行转换。虽然对数变换做得很好,但最佳拟合是无界约翰逊分布。
查看skewness and kurtosis
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
out:
Skewness: 3.259240
Kurtosis: 17.966895
Train_data.skew(), Train_data.kurt()
out:
(SaleID 0.000000
name 0.557606
regDate 0.028495
model 1.484396
brand 1.150662
bodyType 72.267715
fuelType 92.831088
regionCode 9.955996
seller 8.244463
offerType 3.364031
creatDate -2.780338
price 3.259240
v_0 -2.765477
v_1 0.877980
v_2 0.919860
v_3 0.057813
v_4 0.320513
v_5 5.328188
v_6 7.384523
v_7 10.738620
v_8 7.647080
v_9 5.478185
v_10 0.460554
v_11 0.323848
v_12 0.087052
v_13 0.220220
v_14 -1.203489
dtype: float64, SaleID -1.200000
name -1.039945
regDate -0.697308
model 1.740520
brand 1.075831
bodyType 10312.737535
fuelType 17797.327090
regionCode 97.123257
seller 65.972059
offerType 9.316830
creatDate 5.730356
price 17.966895
v_0 6.011055
v_1 0.914529
v_2 3.373838
v_3 -0.432035
v_4 -0.020651
v_5 48.841989
v_6 62.786639
v_7 115.770854
v_8 60.469519
v_9 37.329159
v_10 1.446217
v_11 0.730101
v_12 -0.453978
v_13 -0.357008
v_14 2.350805
dtype: float64)
sns.distplot(Train_data.skew(),color='blue',axlabel ='Skewness')
out:
<matplotlib.axes._subplots.AxesSubplot at 0x7ff016585e80>
sns.distplot(Train_data.kurt(),color='orange',axlabel ='Kurtness')
out:
<matplotlib.axes._subplots.AxesSubplot at 0x7ff00c5ed978>
查看预测值的具体频数
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
out:
查看频数, 大于20000得值极少,其实这里也可以把这些当作特殊得值(异常值)直接用填充或者删掉,再前面进行。
# log变换 z之后的分布较均匀,可以进行log变换进行预测,这也是预测问题常用的trick
plt.hist(np.log(Train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
out:
特征
特征分为类别特征和数字特征,并对类别特征查看unique分布。
数据类型
name | 汽车编码 |
---|---|
regDate | 汽车注册时间 |
model | 车型编码 |
brand | 品牌 |
bodyType | 车身类型 |
fuelType | 燃油类型 |
gearbox | 变速箱 |
power | 汽车功率 |
kilometer | 汽车行驶公里 |
notRepairedDamage | 汽车有尚未修复的损坏 |
regionCode | 看车地区编码 |
seller | 销售方 【以删】 |
offerType | 报价类型 【以删】 |
creatDate | 广告发布时间 |
price | 汽车价格 |
v_0’, ‘v_1’, ‘v_2’, ‘v_3’, ‘v_4’, ‘v_5’, ‘v_6’, ‘v_7’, ‘v_8’, ‘v_9’, ‘v_10’, ‘v_11’, ‘v_12’, ‘v_13’,‘v_14’ | 【匿名特征,包含v0-14在内15个匿名特征】 |
分离label即预测值
Y_train = Train_data['price']
numeric_features = ['power', 'kilometer', 'v_0', 'v_1', 'v_2', 'v_3', 'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13','v_14' ]
categorical_features = ['name', 'model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage', 'regionCode',]
# 特征nunique分布
for cat_fea in categorical_features:
print(cat_fea + "的特征分布如下:")
print("{}特征有个{}不同的值".format(cat_fea, Train_data[cat_fea].nunique()))
print(Train_data[cat_fea].value_counts())
out:
name的特征分布如下:
name特征有个99662不同的值
708 282
387 282
55 280
1541 263
203 233
53 221
713 217
290 197
1186 184
911 182
2044 176
1513 160
1180 158
631 157
893 153
2765 147
473 141
1139 137
1108 132
444 129
306 127
2866 123
2402 116
533 114
1479 113
422 113
4635 110
725 110
964 109
1373 104
...
89083 1
95230 1
164864 1
173060 1
179207 1
181256 1
185354 1
25564 1
19417 1
189324 1
162719 1
191373 1
193422 1
136082 1
140180 1
144278 1
146327 1
148376 1
158621 1
1404 1
15319 1
46022 1
64463 1
976 1
3025 1
5074 1
7123 1
11221 1
13270 1
174485 1
Name: name, Length: 99662, dtype: int64
model的特征分布如下:
model特征有个248不同的值
0.0 11762
19.0 9573
4.0 8445
1.0 6038
29.0 5186
48.0 5052
40.0 4502
26.0 4496
8.0 4391
31.0 3827
13.0 3762
17.0 3121
65.0 2730
49.0 2608
46.0 2454
30.0 2342
44.0 2195
5.0 2063
10.0 2004
21.0 1872
73.0 1789
11.0 1775
23.0 1696
22.0 1524
69.0 1522
63.0 1469
7.0 1460
16.0 1349
88.0 1309
66.0 1250
...
141.0 37
133.0 35
216.0 30
202.0 28
151.0 26
226.0 26
231.0 23
234.0 23
233.0 20
198.0 18
224.0 18
227.0 17
237.0 17
220.0 16
230.0 16
239.0 14
223.0 13
236.0 11
241.0 10
232.0 10
229.0 10
235.0 7
246.0 7
243.0 4
244.0 3
245.0 2
209.0 2
240.0 2
242.0 2
247.0 1
Name: model, Length: 248, dtype: int64
brand的特征分布如下:
brand特征有个40不同的值
0 31480
4 16737
14 16089
10 14249
1 13794
6 10217
9 7306
5 4665
13 3817
11 2945
3 2461
7 2361
16 2223
8 2077
25 2064
27 2053
21 1547
15 1458
19 1388
20 1236
12 1109
22 1085
26 966
30 940
17 913
24 772
28 649
32 592
29 406
37 333
2 321
31 318
18 316
36 228
34 227
33 218
23 186
35 180
38 65
39 9
Name: brand, dtype: int64
bodyType的特征分布如下:
bodyType特征有个8不同的值
0.0 41420
1.0 35272
2.0 30324
3.0 13491
4.0 9609
5.0 7607
6.0 6482
7.0 1289
Name: bodyType, dtype: int64
fuelType的特征分布如下:
fuelType特征有个7不同的值
0.0 91656
1.0 46991
2.0 2212
3.0 262
4.0 118
5.0 45
6.0 36
Name: fuelType, dtype: int64
gearbox的特征分布如下:
gearbox特征有个2不同的值
0.0 111623
1.0 32396
Name: gearbox, dtype: int64
notRepairedDamage的特征分布如下:
notRepairedDamage特征有个2不同的值
0.0 111361
1.0 14315
Name: notRepairedDamage, dtype: int64
regionCode的特征分布如下:
regionCode特征有个7905不同的值
419 369
764 258
125 137
176 136
462 134
428 132
24 130
1184 130
122 129
828 126
70 125
827 120
207 118
1222 117
2418 117
85 116
2615 115
2222 113
759 112
188 111
1757 110
1157 109
2401 107
1069 107
3545 107
424 107
272 107
451 106
450 105
129 105
...
6324 1
7372 1
7500 1
8107 1
2453 1
7942 1
5135 1
6760 1
8070 1
7220 1
8041 1
8012 1
5965 1
823 1
7401 1
8106 1
5224 1
8117 1
7507 1
7989 1
6505 1
6377 1
8042 1
7763 1
7786 1
6414 1
7063 1
4239 1
5931 1
7267 1
Name: regionCode, Length: 7905, dtype: int64
1
# 特征nunique分布
2
for cat_fea in categorical_features:
3
print(cat_fea + "的特征分布如下:")
4
print("{}特征有个{}不同的值".format(cat_fea, Test_data[cat_fea].nunique()))
5
print(Test_data[cat_fea].value_counts())
name的特征分布如下:
name特征有个37453不同的值
55 97
708 96
387 95
1541 88
713 74
53 72
1186 67
203 67
631 65
911 64
2044 62
2866 60
1139 57
893 54
1180 52
2765 50
1108 50
290 48
1513 47
691 45
473 44
299 43
444 41
422 39
964 39
1479 38
1273 38
306 36
725 35
4635 35
..
46786 1
48835 1
165572 1
68204 1
171719 1
59080 1
186062 1
11985 1
147155 1
134869 1
138967 1
173792 1
114403 1
59098 1
59144 1
40679 1
61161 1
128746 1
55022 1
143089 1
14066 1
147187 1
112892 1
46598 1
159481 1
22270 1
89855 1
42752 1
48899 1
11808 1
Name: name, Length: 37453, dtype: int64
model的特征分布如下:
model特征有个247不同的值
0.0 3896
19.0 3245
4.0 3007
1.0 1981
29.0 1742
48.0 1685
26.0 1525
40.0 1409
8.0 1397
31.0 1292
13.0 1210
17.0 1087
65.0 915
49.0 866
46.0 831
30.0 803
10.0 709
5.0 696
44.0 676
21.0 659
11.0 603
23.0 591
73.0 561
69.0 555
7.0 526
63.0 493
22.0 443
16.0 412
66.0 411
88.0 391
...
124.0 9
193.0 9
151.0 8
198.0 8
181.0 8
239.0 7
233.0 7
216.0 7
231.0 6
133.0 6
236.0 6
227.0 6
220.0 5
230.0 5
234.0 4
224.0 4
241.0 4
223.0 4
229.0 3
189.0 3
232.0 3
237.0 3
235.0 2
245.0 2
209.0 2
242.0 1
240.0 1
244.0 1
243.0 1
246.0 1
Name: model, Length: 247, dtype: int64
brand的特征分布如下:
brand特征有个40不同的值
0 10348
4 5763
14 5314
10 4766
1 4532
6 3502
9 2423
5 1569
13 1245
11 919
7 795
3 773
16 771
8 704
25 695
27 650
21 544
15 511
20 450
19 450
12 389
22 363
30 324
17 317
26 303
24 268
28 225
32 193
29 117
31 115
18 106
2 104
37 92
34 77
33 76
36 67
23 62
35 53
38 23
39 2
Name: brand, dtype: int64
bodyType的特征分布如下:
bodyType特征有个8不同的值
0.0 13985
1.0 11882
2.0 9900
3.0 4433
4.0 3303
5.0 2537
6.0 2116
7.0 431
Name: bodyType, dtype: int64
fuelType的特征分布如下:
fuelType特征有个7不同的值
0.0 30656
1.0 15544
2.0 774
3.0 72
4.0 37
6.0 14
5.0 10
Name: fuelType, dtype: int64
gearbox的特征分布如下:
gearbox特征有个2不同的值
0.0 37301
1.0 10789
Name: gearbox, dtype: int64
notRepairedDamage的特征分布如下:
notRepairedDamage特征有个2不同的值
0.0 37249
1.0 4720
Name: notRepairedDamage, dtype: int64
regionCode的特征分布如下:
regionCode特征有个6971不同的值
419 146
764 78
188 52
125 51
759 51
2615 50
462 49
542 44
85 44
1069 43
451 41
828 40
757 39
1688 39
2154 39
1947 39
24 39
2690 38
238 38
2418 38
827 38
1184 38
272 38
233 38
70 37
703 37
2067 37
509 37
360 37
176 37
...
5512 1
7465 1
1290 1
3717 1
1258 1
7401 1
7920 1
7925 1
5151 1
7527 1
7689 1
8114 1
3237 1
6003 1
7335 1
3984 1
7367 1
6001 1
8021 1
3691 1
4920 1
6035 1
3333 1
5382 1
6969 1
7753 1
7463 1
7230 1
826 1
112 1
Name: regionCode, Length: 6971, dtype: int64
数字特征分析
numeric_features.append('price')
numeric_features
out:
['power',
'kilometer',
'v_0',
'v_1',
'v_2',
'v_3',
'v_4',
'v_5',
'v_6',
'v_7',
'v_8',
'v_9',
'v_10',
'v_11',
'v_12',
'v_13',
'v_14',
'price']
4.拓展数据分析
4.1相关性分析
Train_data.corr()
out:
SaleID | name | regDate | model | brand | bodyType | fuelType | regionCode | seller | offerType | ... | v_5 | v_6 | v_7 | v_8 | v_9 | v_10 | v_11 | v_12 | v_13 | v_14 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SaleID | 1.000000 | -0.002299 | -0.001373 | 0.000660 | -0.001732 | 0.001731 | -0.000993 | 0.004634 | -0.000597 | -0.004417 | ... | 0.000799 | -0.001653 | 0.004988 | 0.003994 | -0.000726 | -0.000548 | 0.001607 | -0.001400 | -0.000184 | 0.000369 |
name | -0.002299 | 1.000000 | -0.037638 | 0.016078 | 0.040645 | 0.014921 | 0.025351 | 0.033823 | 0.033498 | 0.041414 | ... | -0.017945 | -0.196067 | 0.045254 | 0.056383 | 0.099972 | 0.518490 | -0.455696 | 0.077569 | 0.015094 | -0.008406 |
regDate | -0.001373 | -0.037638 | 1.000000 | 0.148775 | 0.033143 | 0.027215 | -0.009491 | -0.026464 | -0.045224 | -0.096145 | ... | 0.019967 | 0.009337 | -0.021092 | -0.032470 | -0.068429 | -0.225643 | -0.162924 | 0.758288 | 0.400802 | 0.175593 |
model | 0.000660 | 0.016078 | 0.148775 | 1.000000 | 0.358765 | 0.064201 | -0.009597 | -0.027495 | -0.019166 | -0.040519 | ... | -0.009812 | -0.020172 | -0.038622 | -0.031248 | -0.027764 | -0.044228 | -0.074231 | 0.139551 | 0.350517 | -0.520576 |
brand | -0.001732 | 0.040645 | 0.033143 | 0.358765 | 1.000000 | 0.033365 | -0.004553 | 0.012243 | 0.007847 | 0.002887 | ... | -0.026932 | -0.023120 | 0.000303 | 0.010908 | 0.004324 | 0.045309 | -0.008537 | -0.061771 | 0.301756 | -0.217156 |
bodyType | 0.001731 | 0.014921 | 0.027215 | 0.064201 | 0.033365 | 1.000000 | 0.005745 | 0.211006 | -0.024549 | -0.023040 | ... | -0.033018 | -0.038391 | 0.194565 | 0.163801 | 0.014117 | -0.044802 | -0.086972 | 0.200896 | -0.035155 | -0.293181 |
fuelType | -0.000993 | 0.025351 | -0.009491 | -0.009597 | -0.004553 | 0.005745 | 1.000000 | 0.059550 | 0.493482 | -0.020030 | ... | 0.345303 | 0.000290 | 0.051987 | 0.271383 | 0.324025 | 0.067910 | -0.006850 | 0.006906 | -0.045868 | -0.022277 |
regionCode | 0.004634 | 0.033823 | -0.026464 | -0.027495 | 0.012243 | 0.211006 | 0.059550 | 1.000000 | -0.011941 | -0.027658 | ... | -0.162915 | -0.028290 | 0.957768 | 0.854278 | 0.210124 | -0.012132 | 0.004054 | 0.007157 | 0.002179 | -0.008204 |
seller | -0.000597 | 0.033498 | -0.045224 | -0.019166 | 0.007847 | -0.024549 | 0.493482 | -0.011941 | 1.000000 | -0.032790 | ... | 0.632405 | -0.004083 | -0.017724 | 0.398485 | 0.598812 | 0.100941 | 0.006515 | -0.009076 | 0.000862 | -0.003286 |
offerType | -0.004417 | 0.041414 | -0.096145 | -0.040519 | 0.002887 | -0.023040 | -0.020030 | -0.027658 | -0.032790 | 1.000000 | ... | -0.514306 | 0.426644 | -0.036801 | -0.036941 | 0.264096 | 0.155575 | 0.036072 | -0.009924 | -0.008532 | NaN |
creatDate | 0.002543 | -0.061176 | 0.111367 | 0.052484 | -0.009825 | -0.041082 | -0.201779 | -0.308250 | -0.371028 | -0.852636 | ... | 0.249729 | -0.362205 | -0.283673 | -0.416699 | -0.543799 | -0.172838 | -0.035514 | 0.012979 | 0.008536 | 0.005895 |
price | -0.000975 | -0.006245 | 0.598550 | 0.137851 | -0.045232 | 0.065631 | -0.042423 | -0.074609 | -0.090102 | -0.205467 | ... | 0.093762 | -0.065987 | -0.064177 | -0.090501 | -0.135345 | -0.239397 | -0.335928 | 0.754712 | -0.020419 | 0.027706 |
v_0 | 0.002345 | -0.082468 | 0.194962 | 0.063273 | -0.025070 | -0.027252 | -0.146114 | -0.287991 | -0.275894 | -0.881896 | ... | 0.373620 | -0.365491 | -0.262121 | -0.341200 | -0.487605 | -0.212022 | -0.082141 | 0.139320 | -0.025572 | -0.111194 |
v_1 | -0.000229 | -0.539456 | 0.080587 | 0.003544 | -0.031356 | -0.019824 | 0.011667 | -0.002401 | 0.046620 | 0.113581 | ... | -0.017214 | 0.723588 | -0.003462 | 0.017358 | 0.206387 | -0.578852 | 0.795870 | -0.061195 | -0.011283 | -0.004464 |
v_2 | -0.003768 | -0.133808 | 0.367789 | -0.046379 | -0.103956 | -0.056334 | 0.010476 | 0.026294 | 0.042950 | 0.364442 | ... | -0.164776 | 0.307263 | 0.039352 | 0.050112 | 0.195731 | -0.186694 | -0.042081 | 0.518325 | -0.010709 | 0.172827 |
v_3 | 0.000319 | -0.064480 | -0.761482 | -0.183398 | 0.011806 | -0.080612 | -0.006111 | 0.003479 | 0.008223 | 0.010277 | ... | -0.028031 | 0.015055 | 0.006221 | -0.009272 | 0.012809 | 0.168849 | 0.442290 | -0.907901 | -0.237015 | -0.041099 |
v_4 | -0.000172 | 0.014320 | 0.243291 | 0.398314 | 0.330872 | 0.005294 | 0.002550 | 0.104474 | -0.001612 | 0.041666 | ... | -0.131047 | -0.006691 | 0.084867 | 0.089077 | 0.044172 | 0.058972 | 0.133914 | -0.142758 | 0.922661 | -0.178142 |
v_5 | 0.000799 | -0.017945 | 0.019967 | -0.009812 | -0.026932 | -0.033018 | 0.345303 | -0.162915 | 0.632405 | -0.514306 | ... | 1.000000 | -0.207101 | -0.158314 | 0.251214 | 0.405207 | 0.031855 | -0.060257 | 0.029302 | -0.151337 | -0.081877 |
v_6 | -0.001653 | -0.196067 | 0.009337 | -0.020172 | -0.023120 | -0.038391 | 0.000290 | -0.028290 | -0.004083 | 0.426644 | ... | -0.207101 | 1.000000 | -0.029153 | -0.027000 | 0.409255 | 0.081265 | 0.553215 | -0.035659 | -0.034393 | -0.008391 |
v_7 | 0.004988 | 0.045254 | -0.021092 | -0.038622 | 0.000303 | 0.194565 | 0.051987 | 0.957768 | -0.017724 | -0.036801 | ... | -0.158314 | -0.029153 | 1.000000 | 0.801835 | 0.184555 | -0.012762 | 0.007803 | 0.169300 | -0.399502 | 0.207051 |
v_8 | 0.003994 | 0.056383 | -0.032470 | -0.031248 | 0.010908 | 0.163801 | 0.271383 | 0.854278 | 0.398485 | -0.036941 | ... | 0.251214 | -0.027000 | 0.801835 | 1.000000 | 0.514860 | 0.053681 | -0.006765 | 0.017428 | 0.230892 | 0.026230 |
v_9 | -0.000726 | 0.099972 | -0.068429 | -0.027764 | 0.004324 | 0.014117 | 0.324025 | 0.210124 | 0.598812 | 0.264096 | ... | 0.405207 | 0.409255 | 0.184555 | 0.514860 | 1.000000 | 0.257521 | 0.120078 | -0.021492 | 0.001249 | -0.232794 |
v_10 | -0.000548 | 0.518490 | -0.225643 | -0.044228 | 0.045309 | -0.044802 | 0.067910 | -0.012132 | 0.100941 | 0.155575 | ... | 0.031855 | 0.081265 | -0.012762 | 0.053681 | 0.257521 | 1.000000 | -0.392149 | -0.143136 | 0.015932 | 0.033680 |
v_11 | 0.001607 | -0.455696 | -0.162924 | -0.074231 | -0.008537 | -0.086972 | -0.006850 | 0.004054 | 0.006515 | 0.036072 | ... | -0.060257 | 0.553215 | 0.007803 | -0.006765 | 0.120078 | -0.392149 | 1.000000 | -0.485657 | 0.062519 | 0.098369 |
v_12 | -0.001400 | 0.077569 | 0.758288 | 0.139551 | -0.061771 | 0.200896 | 0.006906 | 0.007157 | -0.009076 | -0.009924 | ... | 0.029302 | -0.035659 | 0.169300 | 0.017428 | -0.021492 | -0.143136 | -0.485657 | 1.000000 | 0.023635 | 0.021549 |
v_13 | -0.000184 | 0.015094 | 0.400802 | 0.350517 | 0.301756 | -0.035155 | -0.045868 | 0.002179 | 0.000862 | -0.008532 | ... | -0.151337 | -0.034393 | -0.399502 | 0.230892 | 0.001249 | 0.015932 | 0.062519 | 0.023635 | 1.000000 | -0.004046 |
v_14 | 0.000369 | -0.008406 | 0.175593 | -0.520576 | -0.217156 | -0.293181 | -0.022277 | -0.008204 | -0.003286 | NaN | ... | -0.081877 | -0.008391 | 0.207051 | 0.026230 | -0.232794 | 0.033680 | 0.098369 | 0.021549 | -0.004046 | 1.000000 |
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')
out:
price 1.000000
v_12 0.692823
v_8 0.685798
v_0 0.628397
power 0.219834
v_5 0.164317
v_2 0.085322
v_6 0.068970
v_1 0.060914
v_14 0.035911
v_13 -0.013993
v_7 -0.053024
v_4 -0.147085
v_9 -0.206205
v_10 -0.246175
v_11 -0.275320
kilometer -0.440519
v_3 -0.730946
Name: price, dtype: float64
f , ax = plt.subplots(figsize = (7, 7))
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
sns.heatmap(correlation,square = True, vmax=0.8)
out:
<matplotlib.axes._subplots.AxesSubplot at 0x7ff01668d940>
4.1查看几个特征得 偏度和峰值
for col in numeric_features:
print('{:15}'.format(col),
'Skewness: {:05.2f}'.format(Train_data[col].skew()) ,
' ' ,
'Kurtosis: {:06.2f}'.format(Train_data[col].kurt())
)
out:
power Skewness: 65.86 Kurtosis: 5733.45
kilometer Skewness: -1.53 Kurtosis: 001.14
v_0 Skewness: -1.32 Kurtosis: 003.99
v_1 Skewness: 00.36 Kurtosis: -01.75
v_2 Skewness: 04.84 Kurtosis: 023.86
v_3 Skewness: 00.11 Kurtosis: -00.42
v_4 Skewness: 00.37 Kurtosis: -00.20
v_5 Skewness: -4.74 Kurtosis: 022.93
v_6 Skewness: 00.37 Kurtosis: -01.74
v_7 Skewness: 05.13 Kurtosis: 025.85
v_8 Skewness: 00.20 Kurtosis: -00.64
v_9 Skewness: 00.42 Kurtosis: -00.32
v_10 Skewness: 00.03 Kurtosis: -00.58
v_11 Skewness: 03.03 Kurtosis: 012.57
v_12 Skewness: 00.37 Kurtosis: 000.27
v_13 Skewness: 00.27 Kurtosis: -00.44
v_14 Skewness: -1.19 Kurtosis: 002.39
price Skewness: 03.35 Kurtosis: 019.00
4.2数字特征可视化
f = pd.melt(Train_data, value_vars=numeric_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")
out:
可以看出匿名特征相对均匀。
4.3 数字特征之间的关系相互可视化
sns.set()
columns = ['price', 'v_12', 'v_8' , 'v_0', 'power', 'v_5', 'v_2', 'v_6', 'v_1', 'v_14']
sns.pairplot(Train_data[columns],size = 2 ,kind ='scatter',diag_kind='kde')
plt.show()
out:
这篇文章是多变量之间的关系可视化,可视化更多学习可参考很不错的文章 https://www.jianshu.com/p/6e18d21a4cad¶
4.4多变量之间相互回归关系可视化
fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6), (ax7, ax8), (ax9, ax10)) = plt.subplots(nrows=5, ncols=2, figsize=(24, 20))
# ['v_12', 'v_8' , 'v_0', 'power', 'v_5', 'v_2', 'v_6', 'v_1', 'v_14']
v_12_scatter_plot = pd.concat([Y_train,Train_data['v_12']],axis = 1)
sns.regplot(x='v_12',y = 'price', data = v_12_scatter_plot,scatter= True, fit_reg=True, ax=ax1)
v_8_scatter_plot = pd.concat([Y_train,Train_data['v_8']],axis = 1)
sns.regplot(x='v_8',y = 'price',data = v_8_scatter_plot,scatter= True, fit_reg=True, ax=ax2)
v_0_scatter_plot = pd.concat([Y_train,Train_data['v_0']],axis = 1)
sns.regplot(x='v_0',y = 'price',data = v_0_scatter_plot,scatter= True, fit_reg=True, ax=ax3)
power_scatter_plot = pd.concat([Y_train,Train_data['power']],axis = 1)
sns.regplot(x='power',y = 'price',data = power_scatter_plot,scatter= True, fit_reg=True, ax=ax4)
v_5_scatter_plot = pd.concat([Y_train,Train_data['v_5']],axis = 1)
sns.regplot(x='v_5',y = 'price',data = v_5_scatter_plot,scatter= True, fit_reg=True, ax=ax5)
v_2_scatter_plot = pd.concat([Y_train,Train_data['v_2']],axis = 1)
sns.regplot(x='v_2',y = 'price',data = v_2_scatter_plot,scatter= True, fit_reg=True, ax=ax6)
v_6_scatter_plot = pd.concat([Y_train,Train_data['v_6']],axis = 1)
sns.regplot(x='v_6',y = 'price',data = v_6_scatter_plot,scatter= True, fit_reg=True, ax=ax7)
v_1_scatter_plot = pd.concat([Y_train,Train_data['v_1']],axis = 1)
sns.regplot(x='v_1',y = 'price',data = v_1_scatter_plot,scatter= True, fit_reg=True, ax=ax8)
v_14_scatter_plot = pd.concat([Y_train,Train_data['v_14']],axis = 1)
sns.regplot(x='v_14',y = 'price',data = v_14_scatter_plot,scatter= True, fit_reg=True, ax=ax9)
v_13_scatter_plot = pd.concat([Y_train,Train_data['v_13']],axis = 1)
sns.regplot(x='v_13',y = 'price',data = v_13_scatter_plot,scatter= True, fit_reg=True, ax=ax10)
out:
<matplotlib.axes._subplots.AxesSubplot at 0x7ff00c9242b0>
5.类别特征分析
5.1unique分布
for fea in categorical_features:
print(Train_data[fea].nunique())
out:
99662
248
40
8
7
2
2
7905
categorical_features
out:
['name',
'model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage',
'regionCode']
5.2类别特征箱型图可视化
# 因为 name和 regionCode的类别太稀疏了,这里我们把不稀疏的几类画一下
categorical_features = ['model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage']
for c in categorical_features:
Train_data[c] = Train_data[c].astype('category')
if Train_data[c].isnull().any():
Train_data[c] = Train_data[c].cat.add_categories(['MISSING'])
Train_data[c] = Train_data[c].fillna('MISSING')
def boxplot(x, y, **kwargs):
sns.boxplot(x=x, y=y)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(boxplot, "value", "price")
out:
5.3 类别特征小提琴图可视化
catg_list = categorical_features
target = 'price'
for catg in catg_list :
sns.violinplot(x=catg, y=target, data=Train_data)
plt.show()
out:
categorical_features = ['model',
'brand',
'bodyType',
'fuelType',
'gearbox',
'notRepairedDamage']
5.4类别特征柱形图可视化
def bar_plot(x, y, **kwargs):
sns.barplot(x=x, y=y)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, id_vars=['price'], value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(bar_plot, "value", "price")
5.5类别特征的每个类别频数可视化
def count_plot(x, **kwargs):
sns.countplot(x=x)
x=plt.xticks(rotation=90)
f = pd.melt(Train_data, value_vars=categorical_features)
g = sns.FacetGrid(f, col="variable", col_wrap=2, sharex=False, sharey=False, size=5)
g = g.map(count_plot, "value")
6.0用pandas_profiling生成数据报告
用pandas_profiling生成一个较为全面的可视化和数据报告(较为简单、方便) 最终打开html文件即可。
import pandas_profiling
pfr = pandas_profiling.ProfileReport(Train_data)
pfr.to_file("./example.html")
7.经验总结
所给出的EDA步骤为广为普遍的步骤,在实际的不管是工程还是比赛过程中,这只是最开始的一步,也是最基本的一步。
接下来一般要结合模型的效果以及特征工程等来分析数据的实际建模情况,根据自己的一些理解,查阅文献,对实际问题做出判断和深入的理解。
最后不断进行EDA与数据处理和挖掘,来到达更好的数据结构和分布以及较为强势相关的特征
数据探索在机器学习中我们一般称为EDA(Exploratory Data Analysis):
是指对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。
数据探索有利于我们发现数据的一些特性,数据之间的关联性,对于后续的特征构建是很有帮助的。
对于数据的初步分析(直接查看数据,或.sum(), .mean(),.descirbe()等统计函数)可以从:样本数量,训练集数量,是否有时间特征,是否是时许问题,特征所表示的含义(非匿名特征),特征类型(字符类似,int,float,time),特征的缺失情况(注意缺失的在数据中的表现形式,有些是空的有些是”NAN”符号等),特征的均值方差情况。
分析记录某些特征值缺失占比30%以上样本的缺失处理,有助于后续的模型验证和调节,分析特征应该是填充(填充方式是什么,均值填充,0填充,众数填充等),还是舍去,还是先做样本分类用不同的特征模型去预测。
对于异常值做专门的分析,分析特征异常的label是否为异常值(或者偏离均值较远或者事特殊符号),异常值是否应该剔除,还是用正常值填充,是记录异常,还是机器本身异常等。
对于Label做专门的分析,分析标签的分布情况等。
进步分析可以通过对特征作图,特征和label联合做图(统计图,离散图),直观了解特征的分布情况,通过这一步也可以发现数据之中的一些异常值等,通过箱型图分析一些特征值的偏离情况,对于特征和特征联合作图,对于特征和label联合作图,分析其中的一些关联性。