1. 程式人生 > >《python資料分析和資料探勘》——資料預處理

《python資料分析和資料探勘》——資料預處理

此文為《python資料分析和資料探勘》的讀書筆記

通俗講,經過我們前期的資料分析,得到了資料的缺陷,那麼我們現在要做的就是去對資料進行預處理,可包括四個部分:資料清洗、資料整合、資料變換、資料規約。

處理過程如圖所示:


1、資料清洗

1) 缺失值處理:

刪除記錄、資料插補、不處理。不處理吧總感覺不自在,刪除了吧資料又有點捨不得,所以一般插補方法用的比較多,該文重點介紹Lagrange插補法和牛頓插補法,並介紹程式碼。

偷點懶他的詳細過程我截圖好了。

a 拉格朗日插補法

    

b 牛頓插補法

         


但是由於python中的Scipy庫中提供了Lagrange插值法的函式,實現上更為容易,應用較多。而牛頓插值法則需要根據自行編寫。需要指出兩者給出的結果是相同的(相同次數、相同係數的多項式),不過表現的形式不同而已。

二話不說貼上親測的python程式碼:

import pandas as pd
from scipy.interpolate import lagrange#匯入拉格朗日函式
import sys
sys.__stdout__=sys.stdout

inputfile='catering_sale.xls'#銷售資料途徑
outputfile='tmp/sales.xls'#輸出資料途徑

data=pd.read_excel(inputfile,Index_col=u'日期')#讀入資料
data[u'銷量'][(data[u'銷量']<400)|(data[u'銷量']>5000)]=None#過濾異常值,將其變為空值

#自定義列向量插值函式
#s為列向量,n為被插值的位置,k為取前後的資料個數,預設為5
def polyinterp_column(s,n,k=5):
    y=s[list(range(n-k,n))+list(range(n+1,n+1+k))]#取數
    y=y[y.notnull()]#剔除空值
    return lagrange(y.index,list(y))(n)#插值並返回插值結果

#逐個元素判斷是否需要插值
#s為列向量,n為被插值的位置,k為取前後的資料個數,預設為5
for i in data.columns:
    for j in range(len(data)):
        if(data[i].isnull())[j]:
            data[i][j]=polyinterp_column(data[i],j)#如果為空即插值

print(str(len(data))+'\n',data)
data.to_excel(outputfile)#輸出結果匯入檔案

具體程式碼作用有相應註釋。

2)異常值處理:異常值是否刪除,要先分析異常值出現的原因,判斷異常值是否應該捨棄。但推薦將其視為缺失值處理,可以利用現有的變數資訊,對異常值進行填補。


2、資料整合

將多個數據源合併存放在一個已知的資料儲存中的過程,需要考慮實體識別和屬性冗餘問題,具體表現在單位要統一、屬性不重複,命名不重合等馬虎原因,該過程屬於人工複查過程。

3、資料變換

規範化處理,滿足挖掘需要。

簡單函式變換:平方、開方、取對數、差分運算等。常用於將不具有正態分佈的資料變換到具有正態分佈的資料。在時間序列分析中簡單的對數變換或差分變換可將非平穩序列轉換成平穩序列,使用對數變換對其進行壓縮是一種常用的一種變換處理方法。

1) 規範化:將資料對映到某一小區間,如歸一化。

a) min-max規範化

 

(data-data.min())/(data.max()-data.min())

b)零-均值規範化——當前應用更廣泛

又稱標準差標準化,經過處理的資料均值為0,標準差為1。轉化公式為


其中為原始資料的均值,為原始資料的標準差。(data-data.mean())/data.std()

c) 小數定標規範化

通過移動屬性值的小數位數,將屬性值對映到[-1, 1]之間,移動的位數取決於屬性值絕對值的最大值。轉化公式為:


data/10**np.ceil(np.log10(data.abs().max()))

2) 連續屬性離散化:在資料範圍內設定若干個離散的劃分點。確定分類數以及如何將連續屬性值對映到這些分類值。

常用的有等寬法(屬性置於劃分成相同寬度的區間)、等頻法(相同數量的記錄放在同一區間)、基於聚類分析的演算法。對聚類分析方法重點說明一下:1.將連續屬性的值用聚類演算法(K-Means演算法)進行聚類 2.將聚類得到的簇進行處理,合併到一個簇的連續屬性值並做同一標記。使用者指定簇的個數從而決定產生的區間數。

對K-Mean的自己理解:隨機一個點作為中心點,設定一個安全距離dist(可以是歐式距離),滿足在dist內的所有點構成一個簇即一個類,然後重新算簇中所有點的平均值,以他為中心點將他安全距離dist內的所有點劃為一類,big重新計算簇中所有點的平均值。大致細節是這樣的,但是我們無法設定距離dist,只能設定期望得到的分類數咯。

#資料規範化
import pandas as pd

datafile='data/discretization_data.xls'#引數規範化
data=pd.read_excel(datafile)#讀取資料
data=data[u'肝氣鬱結證型係數'].copy()#複製整份作為副本
k=4#分成4類

d1=pd.cut(data,k,labels=range(k))#等寬離散化,各個類比一次命名為0,1,2,3

#等頻率離散化
w=[1.0*i/k for i in range(k+1)]
w=data.describe(percentiles=w)[4:4+k+1]#使用describe函式自動計算分位數
w[0]=w[0]*(1-1e-10)
d2=pd.cut(data,w,labels=range(k))

from sklearn.cluster import KMeans#引入KMeans
kmodel=KMeans(n_clusters=k) #建立模型,n_jobs是並行數,一般等於CPU數就好
kmodel.fit(data.values.reshape((len(data),1))) #訓練模型
c=pd.DataFrame(kmodel.cluster_centers_).sort() #輸出聚類中心,並且排序(預設是隨機排序)
w=pd.rolling_mean(c,2).iloc[1:] #相鄰兩項求中點,作為邊界點
w=[0]+list(w[0])+[data.max()] #把首末邊界點加上
d3=pd.cut(data,w,labels=range(k))

import matplotlib.pyplot as plt#自定義左圖函式顯示聚類結果
def cluster_plot(d,k):
    plt.rcParams['font.sans-serif']=['SimHei']  #用來正常顯示中文標籤
    plt.rcParams['axes.unicode_minus']=False#用來正常顯示負號

    plt.figure(figsize=(8,3))
    for j in range(0,k):
        plt.plot(data[d==j],[j for i in d[d==j]],'o')

    plt.ylim(-0.5,k-0.5)
    return plt

cluster_plot(d1,k).show()
cluster_plot(d2,k).show()
cluster_plot(d3,k).show()

3) 屬性構造:該屬性用於衡量標準的一個指標

4) 小波變換:訊號分析手段,在時域和頻域方面具有表徵訊號區域性特徵的能力,用於特徵提取。

應用小波分析技術可以把訊號在各個頻率波段中的特徵提取出來,基於小波變換的多尺度空間能量分佈特徵提取方法是對訊號進行頻帶分析,再分別以計算所得各個頻帶的能量作為特徵向量。訊號f(t)的二級小波分解可表示為

其中A為近似訊號低頻部分;D是細節訊號高頻部分,訊號的頻帶分佈如圖所示


訊號的總能量為:

選擇第j層的近似訊號和各層的細節訊號的能量作為特徵,構造特徵向量:

利用小波變換可以對聲波訊號進行特徵提取,提取出可以代表聲波訊號的向量資料,即完成從聲波訊號到特徵向量資料的變換。本里利用小波函式對聲波訊號資料進行分解得到5個層次的小波係數。利用這些小波係數求得各個能量值,這些能量值即可作為聲波訊號的特徵資料。

在python中訊號處理庫為PyWavelets(pywt)

#利用小波分析進行特徵分析

#引數初始化
inputfile='data/leleccum.mat'#提取自matlab的訊號檔案

from scipy.io import loadmat#mat是Python專用格式,需要用loadmat讀取
mat=loadmat(inputfile)
signal=mat['leleccum'][0]

import pywt#匯入PyWavelets
coeffs=pywt.wavedec(signal,'bior3.7',level=5)
#返回結果為level+1個數字,第一個陣列為逼近係數陣列,後面的一次是細節係數陣列
print(coeffs)

4、資料規約

產生更小但保持原資料完整性的新資料集,降低無效錯誤資料對建模的影響,減少挖掘時間,降低資料存貯成本。

1)屬性規約:聽著這名詞高大上,其實就是刪除不相關的屬性(維)來減少資料維數,尋找出最小的維數確保新資料子集的概率分佈儘可能接近原來資料集的概率分佈。常用方法有合併屬性、逐步向前選擇、逐步向後刪除、決策樹歸納、PCA。

a. 決策樹歸納:我印象中決策樹主要通過比較各個屬性的資訊熵,這個屬性你可以理解成資料的特徵,而一個數據正是有多個特徵或屬性結合而成的行向量。根據一堆資料行向量逐行排成的資料矩陣(行向量資料的列向量)資訊熵的大小,分析出對於該目標向量的最大最有效的屬性,構成一個初始二叉決策樹。沒有出現在決策樹上的屬性均認為是無關屬性。

b. PCA:用較少的變數去解釋原始資料中的大部分變數,即將許多相關性很高的變數轉化成彼此相互獨立或不相關的變數。接下來這段知識,沒學過矩陣理論的大俠就請繞過吧。用矩陣的知識可以這麼解釋:矩陣的列向量所張成的空間即為矩陣所代表的空間,即說明矩陣張成的空間維數等於列向量的列數,而PCA消失的維數代表化零維,即就是矩陣空間中的化零空間N(A),得到的空間成為秩空間R(A),滿足dim(A)=dim(R(A))+dim(N(A))。那麼怎麼得到R(A)呢?——線性變換(+ .)。已知dim(R(A))=r秩,通過A矩陣所代表的平移伸縮,但並不會改變方向的空間向量,這種向量稱之為特徵向量,其伸縮因子稱之為特徵值,這是其幾何顯性意義。那麼就可以通過特徵值去獲得較為全面的矩陣資訊!且特徵值的個數等於矩陣的秩。得到的特徵向量,經矩陣A再反向張開,獲得一個新矩陣來代表資料的有效資訊。本處使用幾何空間去解釋矩陣,可以去了解《控制系統中的矩陣代數》的第一章內容。具體到PCA。

主成分分析的計算步驟:

1)  設原始變數的n次觀測資料矩陣為:


注意是列向量,分別表示某一特徵資料的n次觀測

2)  將資料矩陣陣列進行中心標準化。為了方便仍將標準化後的資料矩陣仍然記為X

3)  求相關係數矩陣R,的定義為:


4)  求R的特徵方程det⁡(R-λE)=0的特徵根(從大到小的排列特徵值)

5)  確定主成分個數m:,根據實際情況確定,一般取80%

6)  計算m個相應的單位特徵向量:


7)  計算主成分:

在python中主成分分析的函式位於Scikit-Learn下:

sklearn.decomposition.PCA(n_components=None,copy=True,whiten=False)

其中whiten表示白化,使得每個特徵具有相同的方差,預設是預設False;

n_components表示PCA演算法要保留的主成分個數,也即要保留下來的特徵個數;

copy表示是否在執行演算法是保留原始訓練資料,複製一份資料副本對其操作,預設為True。

import pandas as pd

#引數初始化
inputfile="data/principal_component.xls"
outputfile='tmp/dimention_reduces.xls'#降維後的資料

data=pd.read_excel(inputfile,header=None)#讀入資料

from sklearn.decomposition import PCA

pca=PCA()
pca.fit(data)
print('各個特徵向量\n',pca.components_)#返回模型的各個特徵向量
print('\n各個成分各自的方差百分比\n',pca.explained_variance_ratio_)#返回各個成分各自的方差百分比
>>> 
各個特徵向量
 [[ 0.56788461  0.2280431   0.23281436  0.22427336  0.3358618   0.43679539
   0.03861081  0.46466998]
 [ 0.64801531  0.24732373 -0.17085432 -0.2089819  -0.36050922 -0.55908747
   0.00186891  0.05910423]
 [-0.45139763  0.23802089 -0.17685792 -0.11843804 -0.05173347 -0.20091919
  -0.00124421  0.80699041]
 [-0.19404741  0.9021939  -0.00730164 -0.01424541  0.03106289  0.12563004
   0.11152105 -0.3448924 ]
 [-0.06133747 -0.03383817  0.12652433  0.64325682 -0.3896425  -0.10681901
   0.63233277  0.04720838]
 [ 0.02579655 -0.06678747  0.12816343 -0.57023937 -0.52642373  0.52280144
   0.31167833  0.0754221 ]
 [-0.03800378  0.09520111  0.15593386  0.34300352 -0.56640021  0.18985251
  -0.69902952  0.04505823]
 [-0.10147399  0.03937889  0.91023327 -0.18760016  0.06193777 -0.34598258
  -0.02090066  0.02137393]]
各個成分各自的方差百分比
 [  7.74011263e-01   1.56949443e-01   4.27594216e-02   2.40659228e-02
   1.50278048e-03   4.10990447e-04   2.07718405e-04   9.24594471e-05]
從上面的結果表明特徵方程有8個特徵值,對應8個特徵向量以及各個成分所佔的各自方差百分比(貢獻率),其中方差百分比越大,說明向量的權重越大。

當選取前4個主成分是,累計貢獻率已達到97.37%,說明前3個主成分進行計算已經相當可以,因此可重新建立PCA模型,設定n_components=3。

#通過分析認為n_components=3最好
pca=PCA(3)
pca.fit(data)
low_d=pca.transform(data)#用它來降低維度
pd.DataFrame(low_d).to_excel(outputfile)#儲存結果
pca.inverse_transform(low_d)#必要時可以用inverse)transform()函式來複原資料
降維後的資料
 [[  8.19133694  16.90402785   3.90991029]
 [  0.28527403  -6.48074989  -4.62870368]
 [-23.70739074  -2.85245701  -0.4965231 ]
 [-14.43202637   2.29917325  -1.50272151]
 [  5.4304568   10.00704077   9.52086923]
 [ 24.15955898  -9.36428589   0.72657857]
 [ -3.66134607  -7.60198615  -2.36439873]
 [ 13.96761214  13.89123979  -6.44917778]
 [ 40.88093588 -13.25685287   4.16539368]
 [ -1.74887665  -4.23112299  -0.58980995]
 [-21.94321959  -2.36645883   1.33203832]
 [-36.70868069  -6.00536554   3.97183515]
 [  3.28750663   4.86380886   1.00424688]
 [  5.99885871   4.19398863  -8.59953736]]

原始資料從8維降到了3維,維持了95%的資料資訊。

2) 數值規約:通過選擇替代的、較小的資料來減少資料量,包括有引數方法和無引數方法兩類。有引數方法是使用一個模型來評估資料只需存放參數,而不需要存放實際資料,例如迴歸(線性迴歸和多元迴歸)和對數線性模型(近似離散屬性集中的多維概率分佈)。無引數的方法就需要存放實際資料,例如直方圖、聚類、抽樣(取樣)。