# 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()`の使い方を覚えておくと便利。