# R - 複数変数から最初の非欠損値を取得する
## 問題設定
コホート研究などで、患者ごとに測定開始時点が異なる場合がある。例えば、ある患者は第1訪問時(x_v1)から測定が開始されるが、別の患者は第2訪問時(x_v2)から測定が開始される。このような状況で、各患者の最初の測定値(ベースライン値)を取得したい。
## サンプルデータ
以下のようなデータフレームを例にする。
```r
df <- data.frame(
x_v1 = c(10, NA, 11, 8, NA),
x_v2 = c(9, 2, 6, NA, NA),
x_v3 = c(5, 8, 5, 3, 9)
)
```
| 行 | x_v1 | x_v2 | x_v3 | 求めたいbase_v |
|----|------|------|------|----------------|
| 1 | 10 | 9 | 5 | 10 |
| 2 | NA | 2 | 8 | 2 |
| 3 | 11 | 6 | 5 | 11 |
| 4 | 8 | NA | 3 | 8 |
| 5 | NA | NA | 9 | 9 |
各行について、x_v1, x_v2, x_v3の順で最初の非欠損値を取得する。
## 方法1: ベタな条件分岐
条件分岐を使って順番にNAを置換する方法。
```r
rm(list = ls())
df <- data.frame(
x_v1 = c(10, NA, 11, 8, NA),
x_v2 = c(9, 2, 6, NA, NA),
x_v3 = c(5, 8, 5, 3, 9)
)
df$base_v <- df$x_v1
df$base_v[is.na(df$x_v1)] <- df$x_v2[is.na(df$x_v1)]
df$base_v[is.na(df$x_v1) & is.na(df$x_v2)] <- df$x_v3[is.na(df$x_v1) & is.na(df$x_v2)]
```
この方法では:
1. まずx_v1をbase_vにコピー
2. x_v1がNAの行については、x_v2で置き換え
3. x_v1とx_v2の両方がNAの行については、x_v3で置き換え
変数が増えると条件が複雑になり、コードが長くなる。
## 方法2: dplyrのcoalesce()関数
dplyrパッケージの`coalesce()`関数を使うと、より簡潔に書ける。
```r
rm(list = ls())
library(dplyr)
df <- data.frame(
x_v1 = c(10, NA, 11, 8, NA),
x_v2 = c(9, 2, 6, NA, NA),
x_v3 = c(5, 8, 5, 3, 9)
)
df <- df %>%
mutate(base_v = coalesce(x_v1, x_v2, x_v3))
```
`coalesce()`関数は、引数として渡された変数を左から順に評価し、最初の非NA値を返す。1行で処理が完了し、変数が増えても引数を追加するだけで対応できる。
## 実行結果
どちらの方法でも、以下の結果が得られる。
```r
print(df)
```
```
x_v1 x_v2 x_v3 base_v
1 10 9 5 10
2 NA 2 8 2
3 11 6 5 11
4 8 NA 3 8
5 NA NA 9 9
```
## まとめ
複数の変数から最初の非欠損値を取得する処理は、条件分岐でも実装できるが、`coalesce()`関数を使う方が:
- コードが短く読みやすい
- 変数が増えても対応しやすい
- 意図が明確
臨床研究のベースライン値設定など、実務でよく使用する処理のため、`coalesce()`の使い方を覚えておくと便利。