EDA-數據探索性分析,是指對已有的數據(特別是調查或觀察得來的原始數據)在儘量少的先驗假定下進行探索,通過作圖、製表、方程擬合、計算特徵量等手段探索數據的結構和規律的一種數據分析方法。
來了解數據,熟悉數據,和數據做朋友;
EDA的目標
EDA的價值主要在於熟悉數據集,瞭解數據集,對數據集進行驗證來確定所獲得數據集可以用於接下來的機器學習或者深度學習使用。
當了解了數據集之後我們下一步就是要去了解變量間的相互關係以及變量與預測值之間的存在關係。
引導數據科學從業者進行數據處理以及特徵工程的步驟,使數據集的結構和特徵集讓接下來的預測問題更加可靠。
完成對於數據的探索性分析,並對於數據進行一些圖表或者文字總結並打卡;
Demo
載入數據科學以及可視化包
首先就是做個調包俠,並學會使用庫包
沒有的庫包,使用 pip install 安裝,即python編譯下的安裝
代碼實現
#!/usr/bin/env python
#coding: utf-8
In[69]:
導入waring包,利用過濾器來實現忽略warning警告
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno
In[10]:
1) 載入訓練集和測試集;
path = 'C:/Users/Administrator/MyFirstJupyter/datalab/' ## 注意這個目錄下的斜杆問題,在這裏面是正斜杆
Train_data = pd.read_csv(path+'used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv(path+'used_car_testA_20200313.csv', sep=' ')
In[11]:
convineent to see
Train_data.head().append(Train_data.tail()) # 頭部加尾部
In[14]:
Train_data.shape
In[16]:
Test_data.head().append(Test_data.tail())
In[17]:
Test_data.shape # 這是什麼意思呢?
總覽數據概況
1、describe種有每列的統計量,個數count、平均值mean、方差std、最小值min、中位數25% 50% 75% 、以及最大值 看這個信息主要是瞬間掌握數據的大概的範圍以及每個值的異常值的判斷,比如有的時候會發現999 9999 -1 等值這些其實都是nan的另外一種表達方式,有的時候需要注意下
2、info 通過info來了解數據每列的type,有助於瞭解是否存在除了nan以外的特殊符號異常
In[18]:
1) 通過describe()來熟悉數據的相關統計量
Train_data.describe()
In[19]:
Test_data.describe() ## 寫出各種中位數
In[20]:
2) 通過info()來熟悉數據類型
Train_data.info()
In[22]:
Test_data.info() ## 測試數據來熟悉數據類型
查看每列的存在nan情況
In[23]:
1) 查看每列的存在nan情況
Train_data.isnull().sum()
In[24]:
Test_data.isnull().sum()
In[25]:
nan可視化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
通過以上兩句可以很直觀的瞭解哪些列存在 “nan”, 並可以把nan的個數打印,主要的目的在於 nan存在的個數是否真的很大,如果很小一般選擇填充,如果使用lgb等樹模型可以直接空缺,讓樹自己去優化,但如果nan存在的過多、可以考慮刪掉
In[28]:
可視化看下缺省值
msno.matrix(Train_data.sample(250)) ## 這個msno 包函數沒有導進去
查看異常值檢測
In[29]:
Train_data.info()
In[30]:
Train_data['notRepairedDamage'].value_counts()
可以看出來‘ - ’也爲空缺值,因爲很多模型對nan有直接的處理,這裏我們先不做處理,先替換成nan
In[31]:
Train_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
Train_data['notRepairedDamage'].value_counts()
In[32]:
Train_data.isnull().sum()
In[33]:
Test_data['notRepairedDamage'].value_counts()
In[34]:
Test_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
以下兩個類別特徵嚴重傾斜,一般不會對預測有什麼幫助,故這邊先刪掉,當然你也可以繼續挖掘,但是一般意義不大
In[35]:
Train_data["seller"].value_counts()
In[36]:
Train_data["offerType"].value_counts()
In[37]:
del Train_data["seller"]
del Train_data["offerType"]
del Test_data["seller"]
del Test_data["offerType"]
瞭解預測值的分佈
In[38]:
Train_data['price']
In[43]:
Train_data['price'].value_counts()
In[44]:
#1) 總體分佈概況(無界約翰遜分佈等)
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)
#價格不服從正態分佈,所以在進行迴歸之前,它必須進行轉換。雖然對數變換做得很好,但最佳擬合是無界約翰遜分佈
In[45]:
2) 查看skewness and kurtosis
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
In[46]:
Train_data.skew(), Train_data.kurt()
In[47]:
sns.distplot(Train_data.skew(),color='blue',axlabel ='Skewness')
In[48]:
sns.distplot(Train_data.kurt(),color='orange',axlabel ='Kurtness')
skew、kurt說明參考https://www.cnblogs.com/wyy1480/p/10474046.html
In[49]:
3) 查看預測值的具體頻數
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
查看頻數, 大於20000得值極少,其實這裏也可以把這些當作特殊得值(異常值)直接用填充或者刪掉,再前面進行
#In[50]:
#log變換 z之後的分佈較均勻,可以進行log變換進行預測,這也是預測問題常用的trick
plt.hist(np.log(Train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
## 特徵分爲類別特徵和數字特徵,並對類別特徵查看unique分佈
#In[51]:
#分離label即預測值
Y_train = Train_data['price']
這個區別方式適用於沒有直接label coding的數據
這裏不適用,需要人爲根據實際含義來區分
數字特徵
numeric_features = Train_data.select_dtypes(include=[np.number])
numeric_features.columns
類型特徵
categorical_features = Train_data.select_dtypes(include=[np.object])
categorical_features.columns
In[52]:
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',]
In[53]:
特徵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())
In[54]:
特徵nunique分佈
for cat_fea in categorical_features:
print(cat_fea + "的特徵分佈如下:")
print("{}特徵有個{}不同的值".format(cat_fea, Test_data[cat_fea].nunique()))
print(Test_data[cat_fea].value_counts())
數字特徵分析
In[55]:
numeric_features.append('price')
In[56]:
numeric_features
In[57]:
Train_data.head()
In[58]:
1) 相關性分析
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')
In[59]:
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)
In[60]:
del price_numeric['price']
In[61]:
2) 查看幾個特徵得 偏度和峯值
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())
)
In[63]:
3) 每個數字特徵得分佈可視化
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")
可以看出匿名特徵相對分佈均勻
In[ ]:
4) 數字特徵相互之間的關係可視化
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()
In[ ]:
Train_data.columns
In[ ]:
Y_train
In[ ]: