要旨
lm()
やglm()
などでは指定した従属変数や独立変数に欠損値がある行が削除される(ペアワイズ)が、ここで削除された行はどんな行なのか確認したいと思ったのでその方法のメモ。
逆に、削除されなかった行たちも確認したいと思った。
また、そもそもこうやって取り出さなくても任意の列(複数列)でNAが含まれていない行のみを取り出したり、逆にNAが含まれている行のみを取り出したいと思ったのでその方法のメモ。
lm()
やglm()
などでペアワイズに削除された行を確認する(そして使われたデータも確認する)
Rのlm()
やglm()
で回帰分析を行うときに従属変数または独立変数に指定した変数に欠損値がある場合、その行は削除されて計算される(ペアワイズ)。
model_lm <- lm(Temp ~ Solar.R + Wind, data = airquality) summary(model_lm)
##
## Call:
## lm(formula = Temp ~ Solar.R + Wind, data = airquality)
##
## Residuals:
## Min 1Q Median 3Q Max
## -17.6521 -5.0358 0.9309 5.0250 18.0943
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 84.899708 2.476595 34.281 < 2e-16 ***
## Solar.R 0.025697 0.007337 3.503 0.000615 ***
## Wind -1.155726 0.188311 -6.137 7.82e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 7.944 on 143 degrees of freedom
## ( 7 個の観測値が欠損のため削除されました )
## Multiple R-squared: 0.2687, Adjusted R-squared: 0.2585
## F-statistic: 26.27 on 2 and 143 DF, p-value: 1.916e-10
ここでペアワイズで除去された行はオブジェクトの中(今回の場合はmodel_lm
)の中にna.action
と行数があるので、model_lm$na.action
で何行目が削除されたのか確認できる。
model_lm$na.action
## 5 6 11 27 96 97 98
## 5 6 11 27 96 97 98
## attr(,"class")
## [1] "omit"
これで元のデータフレームから5、6、11、27、96、97、98行目が削除されたデータフレームで計算されたことがわかる。
どのような行が削除されたのか確認するにはデータフレームでその行を指定すればよいので、次のようにするといい。
airquality[model_lm$na.action, ]
## Ozone Solar.R Wind Temp Month Day
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## 11 7 NA 6.9 74 5 11
## 27 NA NA 8.0 57 5 27
## 96 78 NA 6.9 86 8 4
## 97 35 NA 7.4 85 8 5
## 98 66 NA 4.6 87 8 6
逆に使われた行(削除されていない行)を確認するなら、実際に使われた値(従属変数と独立変数として指定されたもの)だけを取り出したい場合はオブジェクトの中に、model
として格納されているため、次のようにすると取り出せる。
# 長いから実行結果は載せない model_lm$model
また、使わなかった行を指定したときの逆に、使わなかった行じゃない行をデータフレームで指定するとデータフレーム全体を取り出せる。
# 長いから実行しない airquality[-model_lm$na.action, ]
データフレームから任意の列でNAとなっている行を除いたものを取り出す
ところで、今回のlm()
の従属変数や独立変数などのように、任意の列にNA
が含まれている行のみを削除し、そうではない列にNA
が含まれている場合にはとりあえずそのままで取り出すという処理を考えてみる。
つまり任意の列のみを参照しna.omit()
するイメージ、参照されなかったNA
はそのままにしたいということ。ただデータフレームに対してna.omit()
をするとNA
が含まれている行がすべて削除されるので、そこまで削除したくないということ。
任意の列のみからなるデータフレームを作成し、complete.case()
をつかってその中でNA
が含まれていない行を探し、その行をデータフレーム全体で返す処理を考える。
汎用的に使えるように自作関数化する。
na.omit_select <- function(.data, ..., .retrieve = TRUE){ select_case <- stats::complete.cases(dplyr::select(.data = .data, ...)) if(.retrieve) .data[select_case, ] else .data[!select_case, ] }
これは.data
にデータフレームを指定し、...
に参照したい列名を入れるとうまくいく。
例えば次のようなデータフレームを考える。
example_data <- data.frame(value1 = c(1, 2, NA, NA, 10), value2 = c(1, NA, 3:5), value3 = c(NA, 1, 2, NA, 10))
ここでvalue3
でNA
が含まれている行を削除したいと考えると次のようにするといい。
na.omit_select(example_data, value3)
## value1 value2 value3
## 2 2 NA 1
## 3 NA 3 2
## 5 10 5 10
複数の列も指定できる。例として、value2
とvalue3
でNA
が含まれている行を削除してみたい場合は次のようにする。
na.omit_select(example_data, value2, value3)
## value1 value2 value3
## 3 NA 3 2
## 5 10 5 10
逆にNA
が含まれているために除かれた行を取得するには、.retrieve = FALSE
とするとよい。
na.omit_select(example_data, value2, value3, .retrieve = FALSE)
## value1 value2 value3
## 1 1 1 NA
## 2 2 NA 1
## 4 NA 4 NA
どういうデータが欠損値となっているのか見ることができるようになる。
この関数はGitHubにアップしているパッケージに登録している。