在數(shù)據(jù)挖掘中,海量的原始數(shù)據(jù)中存在著大量不完整(有缺失值)、不一致、有異常的數(shù)據(jù),嚴(yán)重影響到數(shù)據(jù)挖掘建模的執(zhí)行效率,甚至可能導(dǎo)致挖掘結(jié)果的偏差,所以進行數(shù)據(jù)清洗就顯得尤為重要,數(shù)據(jù)清洗完成后接著進行或者同時進行數(shù)據(jù)集成、轉(zhuǎn)換、規(guī)約等一系列的處理,該過程就是數(shù)據(jù)預(yù)處理。數(shù)據(jù)預(yù)處理一方面是要提高數(shù)據(jù)的質(zhì)量,另一方面是要讓數(shù)據(jù)更好地適應(yīng)特定的挖掘技術(shù)或工具。統(tǒng)計發(fā)現(xiàn),在數(shù)據(jù)挖掘的過程中,數(shù)據(jù)預(yù)處理工作量占到了整個過程的60%。
數(shù)據(jù)預(yù)處理的主要內(nèi)容包括數(shù)據(jù)清洗、數(shù)據(jù)集成、數(shù)據(jù)變換和數(shù)據(jù)規(guī)約。處理過程如下圖所示:

數(shù)據(jù)清洗
數(shù)據(jù)清洗主要是刪除原始數(shù)據(jù)集中的無關(guān)數(shù)據(jù)、重復(fù)數(shù)據(jù),平滑噪聲數(shù)據(jù),篩選掉與挖掘主題無關(guān)的數(shù)據(jù),處理缺失值、異常值等。
缺失值處理
處理缺失值的方法可分為3類:刪除記錄、數(shù)據(jù)插補和不處理。其中常用的數(shù)據(jù)插補方法如下:
| 插補方法 | 方法描述 |
|---|---|
| 均值/中位數(shù)/眾數(shù)插補 | 根據(jù)屬性值的類型,用該屬性取值的平均數(shù)/中位數(shù)/眾數(shù)進行插補 |
| 使用固定值 | 將缺失的屬性值用一個常量替換。如廣州一個工廠普通外來務(wù)工人員的“基本工資”屬性的空缺值可以用2015年廣州市普通外來務(wù)工人員工資標(biāo)準(zhǔn)1895元/月,該方法就是使用固定值 |
| 最近臨插補 | 在記錄中找到與缺失值最接近的樣本的該屬性值插補 |
| 回歸方法 | 對帶有缺失值的變量,根據(jù)已有數(shù)據(jù)和與其有關(guān)的其他變量(因變量)的數(shù)據(jù)建立擬合模型來預(yù)測缺失的屬性值 |
| 插值法 | 插值法是利用已知點建立合適的插值函數(shù)f(x),未知值由對應(yīng)點xi求出的函數(shù)值f(xi)近似代替 |
如果通過簡單的刪除小部分記錄達(dá)到既定的目標(biāo),那么刪除含有缺失值的記錄的方法是最有效的。然而,這種方法卻有很大的局限性。它是以減少歷史數(shù)據(jù)來換取數(shù)據(jù)的完備,會造成資源的大量浪費,將丟失了大量隱藏在這些記錄中的信息。尤其在數(shù)據(jù)集本來就包含很少記錄的情況下,刪除少量記錄可能會嚴(yán)重影響到分析結(jié)果的客觀性和正確性。一些模型可以將缺失值視作一種特殊的取值,允許直接在含有缺失值的數(shù)據(jù)上進行建模。
(1)拉格朗日插值法
根據(jù)數(shù)學(xué)知識可知,對于平面上已知的n個點(無兩點在一條直線上)可以找到一個n-1次多項式y(tǒng)=a0+a1x+a2x2+...+an-1xn-1,使此多項式曲線過這n個點。
1)求已知的過n個點的n-1次多項式:

將n個點的坐標(biāo)(x1,y1),(x2,y2)...(xn,yn)代入多項式函數(shù),得

解出拉格朗日插值多項式為:


2)將缺失值的函數(shù)值對應(yīng)的點x代入插值多項式得到缺失值的近似值L(x)。
拉格朗日插值公式結(jié)構(gòu)緊湊,在理論分析中很方便,但是當(dāng)插值節(jié)點增減時,這在實際計算中是很不方便的,為了克服這一缺點,提出了牛頓插值法。
(2)牛頓插值法
1)求已知的n個點對(x1,y1),(x2,y2)...(xn,yn)的所有階差商公式

2)建立以上差商公式建立如下插值多項式f(x)

其中:

P(x)是牛頓插值逼近函數(shù),R(x)是誤差函數(shù)。
3)將缺失的函數(shù)值對應(yīng)的點x代入插值多項式得到缺失值的近似值f(x)。
牛頓插值法也是多項式插值,但采用了另一種構(gòu)造插值多項式的方法,與拉格朗日插值相比,具有承襲性和易于變動節(jié)點的特點。從本質(zhì)上來說,兩者給出的結(jié)果是一樣的(相同次數(shù)、相同系數(shù)的多項式),只不過表示的形式不同。因此,在Python的Scipy庫中,只提供了拉格朗日插值法的函數(shù)(因為實現(xiàn)上比較容易),如果需要牛頓插值法,則需要自行編寫函數(shù)。
具體案例
餐飲系統(tǒng)中的銷量數(shù)據(jù)可能會出現(xiàn)缺失值,如下表為某餐廳一段時間的銷量表,其中2015年2月14日的數(shù)據(jù)缺失,用拉格朗日插值法對缺失值進行插補的Python程序如下所示:

# 拉格朗日插值代碼
import pandas as pd # 導(dǎo)入數(shù)據(jù)分析庫Pandas
from scipy.interpolate import lagrange # 導(dǎo)入拉格朗日插值函數(shù)
inputfile = 'data/catering_sale.xls' # 銷量數(shù)據(jù)路徑
outputfile = 'tmp/sales.xls' # 輸出數(shù)據(jù)路徑
data = pd.read_excel(inputfile) # 讀入數(shù)據(jù)
# 過濾異常值,將其變?yōu)榭罩?data[u'銷量'][(data[u'銷量'] < 400) | (data[u'銷量'] > 5000)] = None
# 自定義列向量插值函數(shù)
# s為列向量,n為被插值的位置,k為取前后的數(shù)據(jù)個數(shù),默認(rèn)為5
def ployinterp_columns(s, n, k=5):
y = s[list(range(n - k, n)) + list(range(n + 1, n + 1 + k))] # 取數(shù)
y = y[y.notnull()] # 剔除空值
return lagrange(y.index, list(y))(n) # 插值并返回插值結(jié)果
# 逐個元素判斷是否需要插值
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) # 輸出結(jié)果,寫入文件
應(yīng)用拉格朗日插值法對上表中的缺失值進行插補,使用缺失值前后各5個未缺失的數(shù)據(jù)參與建模,得插值結(jié)果如下所示。
| 時間 | 原始值 | 插值 |
|---|---|---|
| 2015/2/21 | 6607.4 | 4275.255 |
| 2015/2/14 | 空值 | 4156.86 |
異常值處理
在數(shù)據(jù)預(yù)處理時,異常值是否剔除,需視具體情況而定,因為有些異常值蘊含著有用的信息。異常值處理常用方法見下表:

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