R:欠損値処理

データの欠損値は、実際のタスクでは一般的です。 目標がエラーを減らして正確なモデルを構築することである場合、それらを効果的に使用する方法を知る必要があります。 欠損値を処理するためのさまざまなオプションとその実装を見てみましょう。



データセットと準備



mlbenchパッケージのBostonHousingデータセットを使用して、欠損値を処理するさまざまなアプローチを説明します。 BostonHousingのソースデータに欠損値はありませんが、ランダムに導入します。 これにより、データ復旧アプローチの有効性を評価するために、計算された欠損値を実際の欠損値と比較できます。 mlbench



パッケージからデータをインポートし、欠損値(NA)をランダムに入力することから始めましょう。

 #   data ("BostonHousing", package="mlbench") original <- BostonHousing #    #    set.seed(100) BostonHousing[sample(1:nrow(BostonHousing), 40), "rad"] <- NA BostonHousing[sample(1:nrow(BostonHousing), 40), "ptratio"]
      
      





 #> crim zn indus chas nox rm age dis rad tax ptratio b lstat medv #> 1 0.00632 18 2.31 0 0.538 6.575 65.2 4.0900 1 296 15.3 396.90 4.98 24.0 #> 2 0.02731 0 7.07 0 0.469 6.421 78.9 4.9671 2 242 17.8 396.90 9.14 21.6 #> 3 0.02729 0 7.07 0 0.469 7.185 61.1 4.9671 2 242 17.8 392.83 4.03 34.7 #> 4 0.03237 0 2.18 0 0.458 6.998 45.8 6.0622 3 222 18.7 394.63 2.94 33.4 #> 5 0.06905 0 2.18 0 0.458 7.147 54.2 6.0622 3 222 18.7 396.90 5.33 36.2 #> 6 0.02985 0 2.18 0 0.458 6.430 58.7 6.0622 3 222 18.7 394.12 5.21 28.7
      
      





欠損値が入力されました。 そして、それらがどこにあるかはわかっていますが、 mice::md.pattern



少しチェックしましょう。

 #    library(mice) md.pattern(BostonHousing) #     
      
      





 #> crim zn indus chas nox rm age dis tax b lstat medv rad ptratio #> 431 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 #> 35 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 #> 35 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 #> 5 1 1 1 1 1 1 1 1 1 1 1 1 0 0 2 #> 0 0 0 0 0 0 0 0 0 0 0 0 40 40 80
      
      





基本的に、欠損値を処理する方法は4つあります。



1.データの削除



セットに比較的大量のデータが含まれており、必要なすべてのクラスがトレーニングモードデータで十分に表現されている場合、欠損値を含むデータ(行)を削除しようとします(または、 na.action=na.omit



設定など、モデルの作成時に欠損値を無視しないようにします) na.action=na.omit



ます。 データを削除した後、次のことを確認してください。

  1. モデルが信頼性を失わないように十分なポイント。
  2. エラーはありませんでした(つまり、不均衡またはクラスの欠如)。


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





2.変数を削除する



特定の変数の欠損値が他の変数よりも多い場合、それを削除すると、多くのデータを保存できるので、この変数を削除することをお勧めします。 もちろん、それが本当に重要な要素でなければ。 実際、この決定は変数またはデータの一部を失うことです。



3.平均、中央値、ファッションの評価



欠損値を中間値、中央値、またはmodに置き換えることは、それらを操作する粗い方法です。 たとえば、状況によっては、データの変動が小さい場合、またはこの変数が出力にほとんど影響を与えない場合、そのような大まかな近似は受け入れられ、満足のいく結果が得られます。

 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.62324034 4.19306071 2.04769644 0.09545664
      
      





4.予測



予測は、欠損値を置き換える最も難しい方法です。 これには、kNNスコア、rpart、およびマウスのアプローチが含まれます。



4.1。 kNNスコア


DMwR :: knnImputationは、k最近傍法を使用して欠損値を置き換えます。 簡単に言えば、kNN推定は次のことを行います。 置換が必要な各データについて、ユークリッド距離に基づいて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 #> 1.00188715 1.97910183 1.40680554 0.05859526
      
      





パーセント(マップ)の平均絶対誤差は、平均を置き換える場合と比較して約39%改善されました。 悪くない。



4.2 rpart


DMwR::knnImputation



の制限は、因子変数の値が欠落している場合、この関数を使用できない場合があることです。 これにはrpart



mice



両方が適しています。 rpart



の利点は、 NA



含まない変数が少なくとも1つあれば十分であることです。



ここで、 kNN



代わりにkNN



を使用して欠損値を置き換えます。 因子変数を処理するには、 rpart()



呼び出すときにmethod=class



を設定する必要があります。 数値の場合、 method=anova



を使用します。 この場合、出力変数( medv



)がrpart



トレーニングで使用されていないことも確認する必要があります。

 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.71061673 0.99693845 0.99846805 0.04099908
      
      





平均絶対パーセント誤差(マップ)は、kNNスコアと比較してさらに30%向上しました。 とても良い。



radの精度:

 actuals <- original$rad[is.na(BostonHousing$rad)] predicteds <- as.numeric(colnames(rad_pred)[apply(rad_pred, 1, which.max)]) mean(actuals != predicteds) #    
      
      





 #> 0.25
      
      





誤った分類エラー-25%。 因子変数には悪くない!



4.3マウス


mice



(連鎖方程式による多変量代入)の略で、欠損値を操作するための洗練された機能を提供するRパッケージです。 mice()



モデルを構築し、 complete()



データを生成する、わずかに珍しい2段階の推定方法を使用します。 mice(df)



関数は、dfの完全なコピーをいくつか作成します。各コピーには、欠損データの独自の推定値があります。 complete()



関数は1つ以上のデータセットを返します;デフォルトセットが最初になります。 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.36500000 0.78100000 0.88374204 0.02121326
      
      





パーセント(マップ)での平均絶対誤差は、rpartと比較して約48%向上しました。 いいね!



radの精度を計算します。

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





 #> 0.15
      
      





誤った分類エラーは15%に削減されました。 40回の観測のうち6回。 これは、rpartの25%と比較して大幅な改善です。



一般に、それぞれの方法がどれほど優れているかは明らかですが、どちらが優れているか悪いかを確実に言うだけでは十分ではありません。 ただし、欠損値を置換する問題を解決する必要がある場合、それらはすべて注目に値します。



All Articles