資料預處理——資料清洗
在資料探勘中,海量的原始資料中存在著大量不完整、不一致、有異常的資料,嚴重影響到資料探勘建模的執行效率,甚至可能導致挖掘結果的偏差,所以進行資料清洗就顯得尤為重要,資料清洗完成後接著進行或者同時進行資料整合、變換、規約等一系列的處理,該過程就是資料預處理。
資料預處理一方面是要提高資料的質量,另一方面是要讓資料更好地適應特定的挖掘技術或工具。
資料預處理的主要內容包括資料清洗、資料整合、資料變換和資料規約。處理過程如下圖所示:
資料清洗主要是刪除原始資料集中的無關資料、重複資料,平滑噪聲資料,篩選掉與挖掘主題無關的資料,處理缺失值、異常值。
缺失值處理
從統計上說,缺失的資料可能會產生有偏估計,從而使樣本資料不能很好地代表總體,而現實中絕大部分資料都包含缺失值,因此如何缺失值很重要。
一般說來,缺失值的處理包括兩個步驟,即缺失資料的識別和缺失值處理。R語言中缺失值通常以NA表示,可以使用函式is.na()判斷缺失值是否存在,另外函式complete.cases()可識別樣本資料是否完整從而判斷確實情況。在對是否存在缺失值進行判斷之後需要進行缺失值處理,常用的方法有刪除法、替換法、插補法等。
(1)刪除法
刪除法是最簡單的缺失值處理方法,根據資料處理的不同角度可分為刪除觀測樣本、刪除變數兩種。在R中可通過na.omit()函式移除所有含有缺失資料的行,這屬於以減少樣本量來換取資訊完整性的方法,適用於缺失值所佔比例較小的情況;刪除變數適用於變數有較大缺失且對研究目標影響不大的情況,意味著要刪除整個變數,這在R中可通過data[, -p]來實現,p表示缺失變數所在的列。
(2)替換法
變數按屬性可分為數值型和非數值型,二者的處理辦法不同:如果缺失值所在變數為數值型,一般用該變數在其他所有物件的取值的均值來替換變數的缺失值;如果為非數值型變數,則使用該變數其他全部有效觀測值的中位數或者眾數進行替換。
(3)插補法
刪除法雖然簡單易行,但會存在資訊浪費的問題且資料結構會發生變動,以致最後得到有偏的統計結果,替換法也有類似的問題。在面對缺失值問題,常用的插補法有迴歸插補、多重插補等。迴歸插補法利用迴歸模型,將需要插值補缺的變數作為因變數,其他相關變數作為自變數,通過迴歸函式lm()預測出因變數的值來對缺失值進行補缺;多重插補法的原理是從一個包含缺失值的資料集中生成一組完整的資料,如此進行多次,從而產生缺失值的一個隨機樣本,R語言中mice()函式包可以進行多重插補。
下面結合具體案例介紹缺失值的識別和處理。
餐飲系統中的銷量資料可能會出現缺失值,銷量資料的下載地址為:
https://github.com/windform/R/blob/master/R%E8%AF%AD%E8%A8%80%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/%E6%95%B0%E6%8D%AE%E8%B4%A8%E9%87%8F%E5%88%86%E6%9E%90/chapter4/data/catering_sale.csv
下面程式碼將演示均值替換、迴歸插補、多重插補進行缺失資料插補:
> # 讀取銷售資料檔案,提取標題行
> inputfile <- read.csv('./data/catering_sale.csv', header = TRUE)
> # 變換變數名
> inputfile <- data.frame(sales = inputfile$'銷量', date = inputfile$'日期')
> # 資料擷取
> inputfile <- inputfile[5:16, ]
> # 缺失資料的識別
> is.na(inputfile) # 判斷是否存在缺失
sales date
5 FALSE FALSE
6 FALSE FALSE
7 FALSE FALSE
8 FALSE FALSE
9 FALSE FALSE
10 FALSE FALSE
11 FALSE FALSE
12 FALSE FALSE
13 FALSE FALSE
14 FALSE FALSE
15 TRUE FALSE
16 FALSE FALSE
> n <- sum(is.na(inputfile)) # 輸出缺失值個數
> # 異常值識別
> par(mfrow = c(1, 2)) # 將繪圖視窗劃為1行兩列,同時顯示兩圖
> dotchart(inputfile$sales) # 繪製單變數散點圖
> boxplot(inputfile$sales, horizontal = TRUE) # 繪製水平箱形圖
> # 異常資料處理
> inputfile$sales[5] = NA # 將異常值處理成缺失值
> fix(inputfile) # 表格形式呈現資料
> # 缺失值的處理
> inputfile$date <- as.numeric(inputfile$date) # 將日期轉換成數值型變數
> sub <- which(is.na(inputfile$sales)) # 識別缺失值所在行數
> inputfile1 <- inputfile[-sub, ] # 將資料集分成完整資料和缺失資料兩部分
> inputfile2 <- inputfile[sub, ]
> # 行刪除法處理缺失,結果轉存
> result1 <- inputfile1
> # 均值替換法處理缺失,結果轉存
> avg_sales <- mean(inputfile1$sales) # 求變數未缺失部分的均值
> inputfile2$sales <- rep(avg_sales,n) # 用均值替換缺失
> result2 <- rbind(inputfile1, inputfile2) # 併入完成插補的資料
> # 迴歸插補法處理缺失,結果轉存
> model <- lm(sales ~ date, data = inputfile1) # 迴歸模型擬合
> inputfile2$sales <- predict(model, inputfile2) # 模型預測
> result3 <- rbind(inputfile1, inputfile2)
> # 多重插補法處理缺失,結果轉存
> library(lattice) # 調入函式包
> library(MASS)
> library(nnet)
> library(mice) # 前三個包是mice的基礎
> imp <- mice(inputfile, m = 4) # 4重插補,即生成4個無缺失資料集
iter imp variable
1 1 sales
1 2 sales
1 3 sales
1 4 sales
2 1 sales
2 2 sales
2 3 sales
2 4 sales
3 1 sales
3 2 sales
3 3 sales
3 4 sales
4 1 sales
4 2 sales
4 3 sales
4 4 sales
5 1 sales
5 2 sales
5 3 sales
5 4 sales
> fit <- with(imp,lm(sales ~ date, data = inputfile)) # 選擇插補模型
> pooled <- pool(fit)
> summary(pooled)
est se t df Pr(>|t|) lo 95 hi 95 nmis fmi lambda
(Intercept) -8127.53603 6907.61505 -1.176605 6.5448 0.2803675 -24694.59377 8439.5217 NA 0.2095382 0
date 61.87193 37.47189 1.651156 6.5448 0.1456650 -27.99975 151.7436 0 0.2095382 0
> result4 <- complete(imp, action = 3) # 選擇第三個插補資料集作為結果
異常值處理
在異常值處理之前需要對異常值進行識別,一般多采用單變數散點圖或是箱線圖來達到目的。在R語言中,使用函式dotchart()、boxplot()實現繪製單變數散點圖與箱線圖,遠離正常值範圍的點即視為異常值。異常值產生最常見的原因是人為輸入的錯誤。
在資料預處理時,異常值是否剔除,需視具體情況而定,因為有些異常值可能包含有用的資訊,異常值的常用處理方法有:
將含有異常值的記錄直接刪除這種方法簡單易行,但缺點也很明顯,在觀測值很少的情況下,這種刪除會造成樣本量不足,可能會改變變數的原有分佈,從而造成分析結果的不準確。視為缺失值處理的好處是可以利用現有變數的資訊,對異常值進行填補。
很多情況下,要先分析異常值出現的可能原因,再判斷異常值是否應該捨棄,如果是正確的資料,可以直接在具有異常值的資料集上進行挖掘建模。