R語言-缺失值處理1


R語言中缺失值處理

前言

  在處理數據的過程中,樣本往往會包含缺失值。我們有必要對缺失值進行處理,這樣不但可以降低預測分析的數據偏差,而且還可以構建有效的模型。本文將簡要介紹幾種常見的數據缺失值處理方法。

目錄

 1. 數據准備和模式設定

 2. 刪除記錄

 3. 刪除變量

 4. 用均值/中位數/眾數進行插補

 5. 預測法

1. 數據准備和模式設定

  本文所涉及到的幾種數據缺失值處理方法都是使用mlbench包中的BostonHousing數據集作為演示數據。由於BostonHousing數據集沒有缺失值,為了演示需要,在數據集中隨機插入缺失值。通過這種方法,我們不僅可以評估由數據缺失帶來的精度損失,也可以比較不同處理方式的效果好壞。

	# 初始化數據
	# install.packages('mlbench')
	library(mlbench)
	data ("BostonHousing", package="mlbench")
	original <- BostonHousing
	
	# 填充缺失值
	set.seed(100)
	BostonHousing[sample(1:nrow(BostonHousing), 40), "rad"] <- NA
	BostonHousing[sample(1:nrow(BostonHousing), 40), "ptratio"] <- NA

  在插入缺失值之后,我們可以使用mice包中md.pattern函數查看缺失值的“數據模式”

	# 缺失值的模式
	library(mice)
	md.pattern(BostonHousing)
	
	    crim zn indus chas nox rm age dis tax ptratio b lstat medv rad   
	466    1  1     1    1   1  1   1   1   1       1 1     1    1   1  0
	 40    1  1     1    1   1  1   1   1   1       1 1     1    1   0  1
	       0  0     0    0   0  0   0   0   0       0 0     0    0  40 40

 以下是處理缺失值數據的常見四種方法:

2. 刪除記錄

  如果訓練數據集包含有大量的觀測值,那么你可以嘗試刪除包含缺失值的觀測行(或者是在構建模型的時候不包含缺失值,例如設置na.action=na.omit)。在刪除含有缺失值的觀測行之前請確保滿足以下兩個條件:

  • 有足夠樣本點
  • 不會引入偏差

  舉例如下:

	lm(medv ~ ptratio + rad, data=BostonHousing, na.action=na.omit)

3. 刪除變量

  如果數據集中的某個特定變量包含許多的缺失值,並且通過刪除這個特定變量你可以保留許多的觀測值。除非該變量是一個非常重要的預測指標,否則我建議你刪除它。應用這個方法需要我們在變量的重要性和觀測的數量之間做權衡。

4. 用均值/中位數/眾數進行插補

  處理缺失值數據的一種簡單粗暴方法是插補均值、中位數或者眾數。在具體環境下,如果該自變量對因變量的影響比較小,那么這種粗略的估計是可以接受的,並且有可能會產生令人滿意的結果。

  舉例如下:

	library(Hmisc)
	impute(BostonHousing$ptratio, mean)  # 插補均值
	impute(BostonHousing$ptratio, median)  # 插補中位數
	impute(BostonHousing$ptratio, 20)  # 填充特定值
	
	# 手動插值
	BostonHousing$ptratio[is.na(BostonHousing$ptratio)] <- mean(BostonHousing$ptratio, na.rm = T) 

  下面通過均值來插補缺失值,並計算准確度。

	library(DMwR)
	actuals <- original$ptratio[is.na(BostonHousing$ptratio)]
	predicteds <- rep(mean(BostonHousing$ptratio, na.rm=T), length(actuals))
	regr.eval(actuals, predicteds)
	# >       mae        mse       rmse       mape 
	# >  1.65000000 3.91387214 1.97835086 0.09577013 

5. 預測法

  用預測值來處理缺失值的一種高級的方法,主要包括:KNN插值,rpart包,mice包

 5.1 kNN插值法

  DMwR包中的knnImputation函數使用k近鄰方法來填充缺失值。具體過程如下:對於需要插值的記錄,基於歐氏距離計算k個和它最近的觀測。接着將這k個近鄰的數據利用距離逆加權算出填充值,最后用該值替代缺失值。

  該方法的優點是只需調用一次函數就能對所有缺失值進行填充。該函數的參數是除了響應變量之外所有變量組成的數據框。這是因為你無法對未知的響應變量進行插值。

	library(DMwR)
	knnOutput <- knnImputation(BostonHousing[, !names(BostonHousing) %in% "medv"])  # 使用KNN插值.
	anyNA(knnOutput)
	#> FALSE

  檢查精度

	actuals <- original$ptratio[is.na(BostonHousing$ptratio)]
	predicteds <- knnOutput[is.na(BostonHousing$ptratio), "ptratio"]
	regr.eval(actuals, predicteds)
	#>       mae        mse       rmse       mape 
	#>  0.90718277 1.77887569 1.33374499 0.05469914 

  與均值插值法相比,mape的值降低了42.8個百分點。

 5.2 rpart

  knn插值法的缺點是對因子類變量的插補效果不好。rpart包和mice包提供了更靈活的解決方案。rpart的優點是只需一個未缺失值就可以填充整個數據樣本。

  對因子變量而言,rpart函數式可以把method設為class(分類樹)。數值型變量就設定method=anova(回歸樹)。當然,我們也要剔除響應變量。

	library(rpart)
	class_mod <- rpart(rad ~ . - medv, data=BostonHousing[!is.na(BostonHousing$rad), ], method="class", na.action=na.omit)  # rad變量是因子型變量
	anova_mod <- rpart(ptratio ~ . - medv, data=BostonHousing[!is.na(BostonHousing$ptratio), ], method="anova", na.action=na.omit)  # ptratio是數值型變量
	rad_pred <- predict(class_mod, BostonHousing[is.na(BostonHousing$rad), ])
	ptratio_pred <- predict(anova_mod, BostonHousing[is.na(BostonHousing$ptratio), ])

  ptratio的插補精度

	actuals <- original$ptratio[is.na(BostonHousing$ptratio)]
	predicteds <- ptratio_pred
	regr.eval(actuals, predicteds)
	#>       mae        mse       rmse       mape 
	#>0.61655453 0.74165850 0.86119597 0.03643275 

  與knn插值法相比,mape值又額外下降了33.3%。好極了。

  rad的插補精度

	actuals <- original$rad[is.na(BostonHousing$rad)]
	predicteds <- as.numeric(colnames(rad_pred)[apply(rad_pred, 1, which.max)])
	mean(actuals != predicteds)  # 計算誤分類比率
	#> 0.2179487

  僅有21.7%的缺失值被誤分類,這個結果也不壞。

 5.3 mice

  mice是鏈式方程多元插值的簡寫(Multivariate Imputation by Chained Equations)。mice包提供了多種先進的缺失值處理方法。它使用一種不同尋常的方法來進行兩步插值:首先利用mice函數建模再用complete函數生成完整數據。mice(df)會返回df的多個完整副本,每個副本都對缺失的數據插補了不同的值。complete()函數則會返回這些數據集中的一個(默認)或多個。下面演示用該方法如何對rad和ptratio這兩個變量進行插值:

	library(mice)
	miceMod <- mice(BostonHousing[, !names(BostonHousing) %in% "medv"], method="rf")  # 基於隨機森林模型進行mice插值
	miceOutput <- complete(miceMod)  # 生成完整數據
	anyNA(miceOutput)
	#> FALSE

  計算ptratio的插值精度:

	actuals <- original$ptratio[is.na(BostonHousing$ptratio)]
	predicteds <- miceOutput[is.na(BostonHousing$ptratio), "ptratio"]
	regr.eval(actuals, predicteds)
	#>       mae        mse       rmse       mape 
	#> 0.31000000 0.62950000 0.79341036 0.01984801 

  mape值與rpart相比提升了45.8個百分點。

  rad的插補精度:

	actuals <- original$rad[is.na(BostonHousing$rad)]
	predicteds <- miceOutput[is.na(BostonHousing$rad), "rad"]
	mean(actuals != predicteds)  # compute misclass error.
	#>  0.3076923

  誤分類比率為30%,也就是說40個缺失觀測里插補錯誤的只有12個。相對rpart方法的錯誤率(25%)來說,有點稍微的下降。

  如果你想更深入的了解,可以查看mice包的手冊和DataScience+網站上的另一篇文章。

  盡管通過本文你已經對各類處理方法有了初步了解,但這還不足以幫助你判斷每種方法的優劣。當你下次處理缺失值的時候,這些方法是值得一試的。

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM