Python數據分析與挖掘實戰學習筆記(3)

Chapter4 數據預處理

序言

 在數據挖掘中,海量的原始數據中存在着大量不完整(有缺失值)、不一致、有異常的數據,嚴重影響到數據挖掘建模的執行效率,甚至可能導致挖掘結果的偏差,所以進行數據清洗顯得尤爲重要,數據清洗完成後接着進行或者同時進行數據集成、轉換、規約等一系列的處理,該過程就是數據預處理。數據預處理一方面是要提高數據的質量,另一方面是要讓數據更好地適應特定的挖掘技術或工具。

數據清洗

 數據清洗主要是刪除原始數據集中的無關數據、重複數據,平滑噪聲數據,篩選掉與挖掘主題無關的數據,處理缺失值、異常值等。

缺失值處理

 處理缺失值的方法可分爲3類:刪除記錄、數據插補和不處理。其中常用的數據插補方法下下表:

插補方法 方法描述
均值/中位數/衆數插補 根據屬性值的類型,用該屬性值的平均數/中位數/衆數進行插補
使用固定值 將缺失的屬性值用一個常量替換
最近臨插補 在記錄中找到與缺失樣本最接近的樣本的該屬性值插補
迴歸方法 對帶有缺失值的變量,根據已有數據和與其有關的其他變量的數據建立擬合模型來預測缺失的屬性值
插值法 插值法是利用已知點建立合適的插值函數f(x),未知值由對應點xi求出的函數值f(xi)近似代替

 如果通過刪除小部分記錄達到既定的目標,那麼刪除含有缺失值的記錄的方法是最有效的。然而,這種方法卻有很大的侷限性。它是以減少歷史數據來換取數據的完備,會造成資源的大量浪費,將丟棄了大量隱藏在這些記錄中的信息。尤其在數據集本來就包含很少的情況下,刪除少量記錄可能會嚴重影響到分析結果的客觀性和正確性。一些模型可以將缺失值視作一種特殊的取值,允許直接在含有缺失值的數據集上進行建模。
 餐飲系統中的銷量數據可能會出現缺失值,如下表所示,讓我們用拉格朗日插值法進行插補。
在這裏插入圖片描述
拉格朗日插值代碼:

import pandas as pd   # 導入數據分析庫Pandas
from scipy.interpolate import lagrange   # 導入拉格朗日插值函數
inputfile = './data/catering_sale.xls'  # 銷量數據路徑
outputfile = './tmp/sales.xls'  # 輸出數據路徑
data = pd.read_excel(inputfile)  # 讀入數據
data[u'銷量'][(data[u'銷量'] < 400) | (data[u'銷量'] > 5000)] = None  # 過濾異常值,將其變爲空值。
# 自定義列向量插值函數
# s爲列向量,n爲被插值的位置,k爲取前後的數據個數,默認爲5
def ployinterp_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)  # 插值並返回插值結果
# 逐個元素判斷是否需要插值
for i in data.columns:
  for j in range(len(data)):
    if (data[i].isnull())[j]:  # 如果爲空即插值。
      data[i][j] = ployinterp_column(data[i], j)
data.to_excel(outputfile)  # 輸出結果,寫入文件

結果:
在這裏插入圖片描述

異常值處理

 在數據預處理時,異常值是否剔除,需視具體情況而定,因爲有些異常值可能蘊含着有用的信息。異常值常用方法見下表:

異常值處理方法 方法描述
刪除含有異常值的記錄 直接將含有異常值的記錄刪除
視爲缺失值 將異常值視爲缺失值,利用缺失值處理的方法進行處理
平均值修正 可用前後兩個觀測值的平均值修正該異常值
不處理 直接在具有異常值的數據集上進行挖掘建模

 將含有異常值的記錄直接刪除的方法簡單易行,但缺點也很明顯,在觀測值很少的情況下,這種刪除會造成樣本量不足,可能會改變變量的原有分佈,從而造成分析結果的不準確。視爲缺失值處理的好處是可以利用現有變量的信息,對異常值(缺失值)進行填補。
 在很多情況下,要先分析異常值出現的可能原因,再判斷異常值是否應該捨棄,如果是正確的數據,可以直接在具有異常值的數據集上進行挖掘建模。

數據集成

 數據挖掘需要的數據往往分佈在不同的數據源中,數據集成就是將多個數據源合併存放在一個一致的數據存儲(數據倉庫)中的過程。
 在數據集成時,來自多個數據源的現實世界實體的表達形式是不一樣的,有可能不匹配,要考慮實體識別問題和屬性冗餘問題,從而將源數據在最低層上加以轉換、提煉和集成。

實體識別

 實體識別是指從不同數據源識別出現實世界的實體,它的任務是統一不同數據源的矛盾之處,常見形式有:

  1. 同名異義
  2. 異名異義
  3. 單位不統一

冗餘屬性識別

 數據集成往往導致數據冗餘,例如:

  1. 同一屬性多次出現
  2. 同一屬性命名不一致導致重複

 仔細整合不同源數據能減少甚至避免數據冗餘與不一致,從而提高數據挖掘的速度和質量。對於冗餘屬性要先分析,檢測到後再將其刪除。

數據變換

 數據變換主要是對數據進行規範化處理,將數據轉化成“適當的”形式,以適用於挖掘任務及算法的需要。

簡單函數變換

 簡單函數變換是對原始數據進行某些數學函數變換,常用的變換包括平方、開方、取對數、差分運算等。簡單函數變換常用來將不具有正態分佈的數據變換成具有正態分佈的數據。在時間序列分析中,有時簡單的對數變換或者差分運算就可以將非平穩序列轉換成平穩序列。

規範化

 數據規範化(歸一化)處理是數據挖掘的一項基礎工作。不同評價指標往往具有不同的量綱,數值間的差別可能很大,不進行處理可能會影響到數據分析的結果。爲了消除指標間的量綱和取值範圍差異的影響,需要進行標準化處理,將數據按照比例進行縮放,使之落入一個特定的區域,便於進行綜合分析。

# 規範化包括最小-最大規範化(離差標準化)、
# 零-均值規範化(標準差標準化)、小數定標規範化
import pandas as pd
import numpy as np
datafile = './data/normalization_data.xls'  # 參數標準化
data = pd.read_excel(datafile, header=None)  # 讀取數據
normalizeddata1 = (data - data.min()) / (data.max() - data.min())   # 最小-最大規範化
normalizeddata2 = (data - data.mean()) / data.std()   # 零-均值規範化
normalizeddata3 = data / 10**np.ceil(np.log10(data.abs().max()))  # 小數定標規範化
print(data, '\n')  # 查看原始數據
print(normalizeddata1, '\n')  # 查看最小-最大規範化數據
print(normalizeddata2, '\n')  # 查看零-均值規範化數據
print(normalizeddata3)  # 查看小數定標規範化數據
      原始數據
    0    1    2     3
0   78  521  602  2863
1  144 -600 -521  2245
2   95 -457  468 -1283
3   69  596  695  1054
4  190  527  691  2051
5  101  403  470  2487
6  146  413  435  2571 
           最小-最大規範化數據
      0         1         2         3
0  0.074380  0.937291  0.923520  1.000000
1  0.619835  0.000000  0.000000  0.850941
2  0.214876  0.119565  0.813322  0.000000
3  0.000000  1.000000  1.000000  0.563676
4  1.000000  0.942308  0.996711  0.804149
5  0.264463  0.838629  0.814967  0.909310
6  0.636364  0.846990  0.786184  0.929571 
            零-均值規範化數據
          0         1         2         3
0 -0.905383  0.635863  0.464531  0.798149
1  0.604678 -1.587675 -2.193167  0.369390
2 -0.516428 -1.304030  0.147406 -2.078279
3 -1.111301  0.784628  0.684625 -0.456906
4  1.657146  0.647765  0.675159  0.234796
5 -0.379150  0.401807  0.152139  0.537286
6  0.650438  0.421642  0.069308  0.595564 
      小數定標規範化數據
       0      1      2       3
0  0.078  0.521  0.602  0.2863
1  0.144 -0.600 -0.521  0.2245
2  0.095 -0.457  0.468 -0.1283
3  0.069  0.596  0.695  0.1054
4  0.190  0.527  0.691  0.2051
5  0.101  0.403  0.470  0.2487
6  0.146  0.413  0.435  0.2571

連續離散屬性化

 一些數據挖掘算法,特別是某些分類算法(如ID3算法、Apriori算法等),要求數據是分類屬性形式。這樣,常常需要將連續屬性變換成分類屬性,即連續屬性離散化。

離散化過程

 連續屬性離散化就是在數據的取值範圍內設定若干個離散的劃分點,將取值範圍劃分爲一些離散化的區間,最後用不同的符號或整數值代表落在每個子區間中的數據值。離散化涉及的兩個子任務:確定分類數、將連續屬性值映射到這些分類值。

常用的離散化方法

 等寬法、等頻法、基於聚類分析的方法(如k-means算法)

# 下面使用上述的三種離散化方法對“醫學中中醫證型
# 的相關數據”進行連續屬性離散化的對比。
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans  # 引入KMeans
# 數據規範化
datafile = './data/discretization_data.xls'  # 參數初始化
data = pd.read_excel(datafile)  # 讀取數據
data = data[u'肝氣鬱結證型係數'].copy()
k = 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))
# 基於聚類分析的方法
kmodel = KMeans(n_clusters=k, n_jobs=4)  # 建立模型,n_jobs是並行數,一般等於CPU數較好
kmodel.fit(data.values.reshape((len(data), 1)))  # 訓練模型
c = pd.DataFrame(kmodel.cluster_centers_).sort_values(0)  # 輸出聚類中心,並且排序(默認是隨機序的)
w = c.rolling(2).mean().iloc[1:]  # 相鄰兩項求中點,作爲邊界點
w = [0] + list(w[0]) + [data.max()]  # 把首末邊界點加上
d3 = pd.cut(data, w, labels=range(k))
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%-15%,
# 如果遠遠超過該範圍,就可以認爲該條線路的大用戶很可能
# 存在竊漏電等用電異常行爲。
# 由供入電量、供出電量進行線損率的屬性構造
import pandas as pd
# 參數初始化
inputfile = './data/electricity_data.xls'  # 供入供出電量數據
outputfile = './tmp/electricity_data.xls'  # 屬性構造後數據文件
data = pd.read_excel(inputfile)  # 讀入數據
data[u'線損率'] = (data[u'供入電量'] - data[u'供出電量']) / data[u'供入電量']
data.to_excel(outputfile, index=False)  # 保存結果

小波變換

  小波變換具有多分辨率的特點,在時域和頻域都具有表徵局部信號的能力,通過伸縮和平移等運算過程對信號進行多尺度聚焦分析,提供了一種非平穩信號的時頻分析手段,小波變換可以把非平穩信號分解爲表達不同的層次、不同頻帶信息的數據序列,即小波係數,可以由粗及細地逐步觀察信號,從中提取出有用的信息。基於小波變換的特徵提取方法:基於小波變換的多尺度空間能量分佈特徵提取、基於小波變換的多尺度空間的模極大值特徵提取、基於小波包變換的特徵提取、基於適應性小波神經網絡的特徵提取。

# 利用小波分析進行特徵分析:
import pandas as pd
from scipy.io import loadmat  # mat是Python專用格式,需要用loadmat讀取它。
import pywt  # 導入PyWavelets
inputfile = './data/leleccum.mat'  # 參數初始化-----提取自Matlab的信號文件
mat = loadmat(inputfile)
signal = mat['leleccum'][0]
# 返回結果爲level+1個數字,第一個數組爲逼近係數數組,後面的依次是細節係數數組
coeffs = pywt.wavedec(signal, 'bior3.7', level=5)
print(coeffs)
 部分結果:
[2415.1478541 , 2395.74470824, 2402.22022728, 2408.90987352,
   2402.22022728, 2395.74470824, 2415.1478541 , 2369.53622493,
   1958.0913368 , 1983.87619596, 1901.68851538, 1651.86483216,
   1482.45129628, 1356.98779058, 1257.4459793 , 1265.75505172,
   1363.66712581, 1427.53767222, 1568.87951307, 1893.80694993,
   2295.89161125, 2555.9239482 , 2778.31817145, 2871.0940301 ,...]

數據規約

 在大數據集上進行復雜的數據分析和挖掘需要很長的時間,數據規約產生更小但擔保原數據完整性的新數據集。在規約後的數據集上進行分析和挖掘將更加有效率。
數據規約的意義:

  1. 降低無效或錯誤數據對建模的影響,提高數據的準確性;
  2. 少量且具有代表性的數據將大幅縮減數據挖掘所需的時間;
  3. 降低存儲數據的成本。

屬性規約

 屬性規約通過屬性合併來創建新屬性維數,或者直接通過刪除不相關屬性(維)來減少數據的維數,從而提高數據挖掘的效率、降低計算成本。屬性規約的目標是尋找出最小的屬性子集並確保新數據子集的概率分佈儘可能地接近原來數據集的概率分佈。
屬性規約常用方法:
 合併屬性、逐步向前選擇、逐步向後刪除、決策樹歸納、主成分分析(PCA)
PCA算法:
 它是一種用於連續屬性的數據降維方法,它構造了原始數據的一個正交變換,新空間的基底去除了原始空間基底下的數據的相關性,只需使用少數新變量就能夠解釋原始數據中的大部分變異。

# 主成分分析代碼
import pandas as pd
from sklearn.decomposition import PCA
# 參數初始化
inputfile = './data/principal_component.xls'
data = pd.read_excel(inputfile, header=None)  # 讀入數據
pca = PCA()
pca.fit(data)
print(pca.components_, '\n')  # 返回模型的各個特徵向量
print(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] (模型的各個成分各自的方差百分比(貢獻率))

由結果可知,當選取前4個成分時,累計貢獻率已達到97.37%,說明選取前3個主成分進行計算已經相當不錯了,因此可以重新建立PCA模型。

# 設置n_components=3, 計算出成分結果:
import pandas as pd
from sklearn.decomposition import PCA
# 參數初始化
inputfile = './data/principal_component.xls'
outputfile = './tmp/dimention_reducted.xls'  # 降維後的數據
data = pd.read_excel(inputfile, header=None)  # 讀入數據
pca = PCA(3)
pca.fit(data)
low_d = pca.transform(data)  # 用它來降低維度
pd.DataFrame(low_d).to_excel(outputfile)  # 保存結果
pca.inverse_transform(low_d)  # 必要時可以用inverse_transfrom()函數來複原數據
print(low_d)

[[ 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維,同時這3維數據佔了原始數據95%以上的信息。

數值規約

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

小結

 本章主要介紹了數據預處理的4個主要任務:數據清洗、數據集成、數據變換和數據規約。數據清洗主要介紹了對缺失值和異常值的處理,延續了第三章的缺失值和異常值分析的內容,本章主要介紹的處理缺失值的方法分爲3類:刪除記錄、數據插補和不處理,處理異常值的方法有刪除含有異常值的記錄、不處理、平均值修正和視爲缺失值;數據集成是合併多個數據源中的數據,並存放到一個數據存儲的過程,對該部分的介紹從實體識別問題和冗餘屬性兩個方面進行;數據變換介紹瞭如何從不同角度對已有屬性進行函數變換;數據規約從屬性(縱向)規約和數值(橫向)規約兩個方面介紹瞭如何對數據進行規約,使挖掘的性能和效率得到了很大的提高。通過對原始數據的處理,將爲後續挖掘建模提供良好的數據基礎。

發佈了9 篇原創文章 · 獲贊 67 · 訪問量 5679
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章