Rによる欠損値処理

今回は機械学習などでモデルを作る際に必須となる欠損値の扱いをtidyverseを用いて実装します。
欠損値の生成メカニズムなどの理論的な話は、参考サイトや参考文献をご覧ください。


#データセットの確認
今回はR組み込みデータセットのairqualityデータセットを使用します。

```R
#使用パッケージの読み込み
library(tidyverse)
library(skimr)
library(modelr)
```


```R
#データの確認
data("airquality")
df <- airquality
df %>% head()
```

```R
#出力
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6
```
欠損値が確認できますね。


↓skimrパッケージは欠損データの確認に便利です

```R
df %>% skimr::skim()
```


```R
#出力
Skim summary statistics
 n obs: 153 
 n variables: 6 

-- Variable type:integer -------------------------------------------------------
 variable missing complete   n   mean    sd p0    p25   p50    p75 p100
      Day       0      153 153  15.8   8.86  1   8     16    23      31
    Month       0      153 153   6.99  1.42  5   6      7     8       9
    Ozone      37      116 153  42.13 32.99  1  18     31.5  63.25  168
  Solar.R       7      146 153 185.93 90.06  7 115.75 205   258.75  334
     Temp       0      153 153  77.88  9.47 56  72     79    85      97
     hist
 ▇▇▇▇▆▇▇▇
 ▇▇▁▇▁▇▁▇
 ▇▆▃▃▂▁▁▁
 ▃▃▃▃▅▇▇▃
 ▂▂▃▆▇▇▃▃

-- Variable type:numeric -------------------------------------------------------
 variable missing complete   n  mean   sd  p0 p25 p50  p75 p100     hist
     Wind       0      153 153  9.96 3.52 1.7 7.4 9.7 11.5 20.7 ▁▃▇▇▅▅▁▁

```
この結果から、Ozone、Solar.Rに欠損値が含まれていることがわかります。
以下、簡単のためOzoneの欠損値に絞って記載します。

#リストワイズ法(lisewise deletion)
欠損値が一つでもあるデータを除きます。

```R
df_lw <- 
  na.omit(df)
```
```R
df_lw %>%  head()
```


```R
#出力
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
7    23     299  8.6   65     5   7
8    19      99 13.8   59     5   8
```

#平均値代入法(mean imputation)
欠損値を平均値で置き換えます。

```R
df_mi <-
  df %>% 
  mutate(Ozone_new=if_else(condition = is.na(Ozone),
                           true = mean(Ozone,na.rm = T),
                           false = Ozone %>% as.double()))

```
```R
df_mi %>%  head()
```


```R
#出力
  Ozone Solar.R Wind Temp Month Day Ozone_new
1    41     190  7.4   67     5   1  41.00000
2    36     118  8.0   72     5   2  36.00000
3    12     149 12.6   74     5   3  12.00000
4    18     313 11.5   62     5   4  18.00000
5    NA      NA 14.3   56     5   5  42.12931
6    28      NA 14.9   66     5   6  28.00000
```




#回帰代入法(regression imputation)
回帰モデルを用いて予測した値で置き換えます。

```R
#回帰モデル作成(今回はWindを用いて1次回帰しています。)
model_lm=
  lm(formula = Ozone~Wind,data = df)

df_ri <-
df %>% 
  add_predictions(model = model_lm,var = "Ozone_pred") %>% 
  mutate(Ozone_new=if_else(condition = is.na(Ozone),
                           true = Ozone_pred,
                           false = Ozone %>% as.double())) %>% 
  select(-Ozone_pred)
```
```R
df_ri %>%  head()
```


```R
#出力
  Ozone Solar.R Wind Temp Month Day Ozone_new
1    41     190  7.4   67     5   1   41.0000
2    36     118  8.0   72     5   2   36.0000
3    12     149 12.6   74     5   3   12.0000
4    18     313 11.5   62     5   4   18.0000
5    NA      NA 14.3   56     5   5   17.4947
6    28      NA 14.9   66     5   6   28.0000
```

回帰モデルでなくても、KNNやRandomForestなども使えます。


###参考
[データ分析プロセス (シリーズ Useful R 2)](https://www.amazon.co.jp/%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9-%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Useful-R-2/dp/4320123654/ref=sr_1_1?adgrpid=56128276714&gclid=CjwKCAjw-4_mBRBuEiwA5xnFIO027Bwm-5Ue0EdqNHbB5x_Qw4Uc7A-fzd0UbP7U4hTQWZ4_oEVGpxoC4KcQAvD_BwE&hvadid=338584091456&hvdev=c&hvlocphy=1009647&hvnetw=g&hvpos=1t1&hvqmt=b&hvrand=10078824861621875957&hvtargid=kwd-373829657481&hydadcr=4072_10899412&jp-ad-ap=0&keywords=%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9&qid=1556363758&s=gateway&sr=8-1)
[Rで実践！欠損データ分析入門](https://techblog.nhn-techorus.com/archives/6309)
[データ前処理〜欠損値への対応〜](http://rtokei.tech/datawrangling/%E3%83%87%E3%83%BC%E3%82%BF%E5%89%8D%E5%87%A6%E7%90%86%E3%80%9C%E6%AC%A0%E6%90%8D%E5%80%A4%E3%81%B8%E3%81%AE%E5%AF%BE%E5%BF%9C%E3%80%9C/)
[データ前処理〜データの要約〜](http://rtokei.tech/datawrangling/%E3%83%87%E3%83%BC%E3%82%BF%E5%89%8D%E5%87%A6%E7%90%86%E3%80%9C%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E8%A6%81%E7%B4%84%E3%80%9C/)
[skimrパッケージ](https://github.com/ropensci/skimr)