寫在前面(這部分是廢話)
這是參加 datawhale 數據挖掘的第一次打卡,打卡內容是數據分析,希望自己能堅持做下去。開始的時候,第一天看了一下題目背景,運行了一下 baseline,剛好中期報告要改,就放下了。今天在這裏做一下數據分析這部分的筆記。
介紹
本文主要是根據天池上的教程進行學習的,一些不理解地方做了筆記,內容沒有教程全,附上教程鏈接:Datawhale 零基礎入門數據挖掘-Task2 數據分析
數據分析主要的三個工具: pandas、numpy、scipy。(以前只用過 numpy)
可視化的兩個主要工具: matplotlib、seabon。(以前只用過 matplotib)
接下來通過代碼加個人理解記錄一下數據分析的過程。
數據分析過程
環境配置就不記錄了,很無聊。首先需要導入一下包:
#coding:utf-8
#導入warnings包,利用過濾器來實現忽略警告語句。
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
後續代碼默認使用如上導入的包。
載入數據
path = './data/'
Train_data = pd.read_csv(path+'used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv(path+'used_car_testA_20200313.csv', sep=' ')
print(Train_data.shape)
print(Test_data.shape)
輸出:
(150000, 31)
(50000, 30)
使用 pands
庫可以很方便地讀取數據。這裏的 pd.read_csv()
函數有很多參數,這裏只設置了兩個: filepath_or_buffer
參數表示文件的路徑; sep
表示數據使用什麼符號分隔的,默認 sep = ','
。還有很多其他參數,如 index_col
指定讀取哪寫列數據、shkiprows=n
跳過前 n 行數據…
查看數據
pd.read_csv()
函數返回的數據類型是 DataFrame
,是 pandas
中特有的數據類型,相當於高級版的二維數組,可以通過它實現很多操作,封裝了很多處理數據的函數。
關於 DataFrame
更多方法介紹,建議參考 python下的Pandas中DataFrame基本操作(一),基本函數整理
head(n=5)
可以通過 head(n)
函數展示數據的前 n
行數據,默認 n=5
。
print(Train_data.head())
運行結果:
tail(n=5)
與 head()
函數相反,tail(n)
函數返回的是數據後 n 行數據,默認 n=5
。
print(Train_data.tail())
運行結果:
總覽數據
在查看了數據之後,對數據的樣子就會有個大概的認識。但更多時候,只是查看數據長什麼樣子是不夠的,還需要查看數據的性質,包括數據方差、個數等等。下面是幾個常用的總覽數據的方法。
describe(percentiles=None, include=None, exclude=None)
describe()
是針對 pandas
中 Series
或 DataFrame
所有的列進行數據統計的一種方法。函數是用來查看數值特徵的一些信息,返回特徵的總數、均值、標準差、最小值、分位數、最大值。
這裏解釋下函數的三個參數,具體理解,還請參考官網 pandas-dataframe-describe
-
percentiles:數組類型,表示分位線。所有值應該是(0,1)之間的小數,默認是 [.25, .5, .75],返回 25%, 50%和75%
-
include, exclude : 列表類型,指定輸出結果的形式。分三種情況,當二者都爲
None
時,結果只包含數值類型的統計信息;如果是一組dtypes
或strings
,所有數值類型使用numpy.number
,類別屬性使用type
;如果include='all'
,則輸出的列與輸入相同。
示例:
print(Train_data.describe())
運行結果:
其中,百分數 25%, 50%和75% 表示分位數,表示在把所有數值由小到大排序,並分成四等份,處於三個分割點位置的數值。
info(verbose=None, buf=None, max_cols=None, memory_usage=None, null_counts=None)
info()
函數可以用來查看 DataFrame 信息, 能夠簡要看到對應一些數據列名,瞭解數據每列的 type,以及 NAN 缺失信息。
參數介紹:
- verbose:如果爲True,則顯示所有列;如果爲False,則會省略一部分。
- buf:結果輸出到的位置。
- max_cols:輸出列的最大數目,超過則進行縮減輸出。
- memory_usage:是否顯示 DataFrame 的內存使用情況,缺省(None)時,默認爲 True。
- null_counts:是否顯示非空計數。
示例:
print(Train_data.info())
運行結果:
數據缺失和異常
統計數據信息查看完後,還要進一步查看數據是否異常,如 nan 或 null。
isnull()
isnull()
函數,以布爾的方式返回所有數據是否爲 null 的信息,返回值的類型也是 DataFrame
。
示例:
Train_data.isnull().sum()
運行結果:
其中,sum()
函數按列進行求和,返回一個 Series
類型的值。
缺失數據的可視化
示例:
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar() # 垂直條形圖
plt.show()
運行結果:
示例:
msno.matrix(Train_data.sample(250))
plt.show()
sample()
函數表示隨機選取若干行。
運行結果:
示例:
msno.bar(Train_data.sample(1000))
plt.show()
統計信息
查看類型爲 object
特徵:
print(Train_data['notRepairedDamage'].value_counts())
輸出:
0.0 111361
- 24324
1.0 14315 Name: notRepairedDamage, dtype: int64
將值替換成 nan:
Train_data['notRepairedDamage'].replace('-', np.nan, inplace=True)
print(Train_data['notRepairedDamage'].value_counts())
輸出:
0.0 111361
1.0 14315
Name: notRepairedDamage, dtype: int64
去掉傾斜嚴重的特徵
查看以下兩個特徵(按照教程做的,事先肯定不知道哪個特徵嚴重傾斜)
print(Train_data["seller"].value_counts())
print(Train_data["offerType"].value_counts())
輸出:
0 149999
1 1
Name: seller, dtype: int64
0 150000
Name: offerType, dtype: int64
分析數據分佈
查看要預測數據(price)的分佈信息:
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)
plt.show()
就不展示圖像了。
查看偏度和峯度
簡單理解一下偏度和峯度的概念,參考:數據的偏度和峯度——df.skew()、df.kurt()
-
偏度: 表示數據總體取值分佈的對稱性。
-
峯度: 表示數據分佈頂的尖銳程度。
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
plt.show()
運行結果:
Skewness: 3.346487
Kurtosis: 18.995183
查看幀數,更具體地查看數據分佈
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
# log 變換後的分佈
plt.hist(np.log(Train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()
會發現大於 20000 的數據很少。
做 log 之後的數據分佈圖:
會發現數據分佈不像之前那樣集中了。
特徵分類
select_dtypes()
特徵分爲類別特徵和數字特徵。可以使用 select_dtypes()
函數查看兩種特徵各包含哪些列:
# 數字特徵
numeric_features = Train_data.select_dtypes(include=[np.number])
print(numeric_features.columns)
# 類別特徵
categorical_features = Train_data.select_dtypes(include=[np.object])
print(categorical_features.columns)
運行結果:
Index([‘SaleID’, ‘name’, ‘regDate’, ‘model’, ‘brand’, ‘bodyType’, ‘fuelType’,
‘gearbox’, ‘power’, ‘kilometer’, ‘regionCode’, ‘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’],
dtype=‘object’)
Index([‘notRepairedDamage’], dtype=‘object’)
注意:這個區別方式適用於沒有直接label coding的數據,這裏把很多類別特徵用數字表示了,因此該方法在該比賽中不適用,需要人爲根據實際含義來區分
unique() 和 nunique()
unique()
函數返回的是特徵的所有唯一值;nunique()
函數返回的是特徵中所有唯一值的個數。
示例,查看每個分類特徵的分佈:
# 特徵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())
接下來詳細介紹一下數字特徵和類別特徵。
數字特徵分析
好多啊,,,後面兩部分簡寫一下。。。
1. 使用 corr() 分析相關性
corr()
函數返回的是各個特徵之間的相關係數,是 DataFrame
類型。
示例:
# 數字特徵
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' ]
numeric_features.append('price')
## 1) 相關性分析
price_numeric = Train_data[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')
運行結果:
以熱力圖的形式畫出各個數字特徵之間的相關係數:
# 畫相關係數圖
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
sns.heatmap(correlation, square=True, vmax=0.8)
plt.show()
運行結果:
關於熱力圖的畫法,參考:sns.heatmap的用法簡介
2. 查看各個特徵的偏度和峯度
示例:
## 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())
)
運行結果:
3. 每個數字特徵得分佈可視化
示例:
## 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")
plt.show()
melt()
函數是一個逆轉操作,其中的 value_vars
參數表示需要轉換的列名。
運行結果:
4. 數字特徵相互之間的關係可視化
## 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()
5. 多變量互相迴歸關係可視化
分類特徵
好多畫圖的,不想記錄了,這部分簡寫一下。
-
unique分佈(前面記錄了)
-
類別特徵箱形圖可視化
-
類別特徵的小提琴圖可視化
-
類別特徵的柱形圖可視化
-
類別特徵的每個類別頻數可視化(count_plot)
pandas_profiling
最後,可以用 pandas_profiling
生成一個較爲全面的可視化和數據報告。
最後
後面的內容就簡單寫了一下過程,後續還會補充點東西,主要是瞭解整個數據分析的過程。