複数のデータフレームを結合する操作は、データ分析において頻繁に必要となります。Rには標準で`merge()`関数が用意されており、追加パッケージをインストールすることなくデータ結合を行うことができます。
この記事では、base Rの`merge()`関数を使った基本的なデータ結合の方法を、患者データと体重データを例にして解説します。
tidyverseパッケージを使った応用的な方法については[[R - データ結合(tidyverse)]]を参照してください。
## 完全なコード
```r
# サンプルデータ1: 患者の基本情報
patients <- data.frame(
  id = c(1001, 1002, 1003, 1004, 1005),
  name = c("山田太郎", "田中花子", "佐藤次郎", "鈴木美咲", "高橋健太"),
  age = c(45, 32, 67, 28, 51)
)
# サンプルデータ2: 体重データ
weights <- data.frame(
  id = c(1001, 1002, 1003, 1005, 1006),
  weight_kg = c(70, 52, 82, 55, 75)
)
# 内部結合 - 両方のデータが存在する患者のみ
inner_result <- merge(patients, weights, by = "id")
print("内部結合の結果:")
print(inner_result)
# 左外部結合 - 全ての患者情報を保持(体重データがない場合はNA)
left_result <- merge(patients, weights, by = "id", all.x = TRUE)
print("左外部結合の結果:")
print(left_result)
# 右外部結合 - 全ての体重データを保持(患者情報がない場合はNA)
right_result <- merge(patients, weights, by = "id", all.y = TRUE)
print("右外部結合の結果:")
print(right_result)
# 完全外部結合 - 両方のデータを全て保持
full_result <- merge(patients, weights, by = "id", all = TRUE)
print("完全外部結合の結果:")
print(full_result)
```
## ステップバイステップ解説
### 1. サンプルデータの作成
まず患者の基本情報を作成します:
```r
patients <- data.frame(
  id = c(1001, 1002, 1003, 1004, 1005),
  name = c("山田太郎", "田中花子", "佐藤次郎", "鈴木美咲", "高橋健太"),
  age = c(45, 32, 67, 28, 51)
)
```
```
> print(patients)
    id     name age
1 1001   山田太郎  45
2 1002   田中花子  32
3 1003   佐藤次郎  67
4 1004   鈴木美咲  28
5 1005   高橋健太  51
```
次に体重データを作成します:
```r
weights <- data.frame(
  id = c(1001, 1002, 1003, 1005, 1006),
  weight_kg = c(70, 52, 82, 55, 75)
)
```
```
> print(weights)
    id weight_kg
1 1001        70
2 1002        52
3 1003        82
4 1005        55
5 1006        75
```
注目すべき点は、患者データにはid 1004が含まれていますが体重データにはなく、逆に体重データにはid 1006が含まれていますが患者データにはないということです。この違いによって、各結合操作の結果がどのように変わるかを確認できます。
### 2. 内部結合(Inner Join)
```r
inner_result <- merge(patients, weights, by = "id")
```
```
> print(inner_result)
    id     name age weight_kg
1 1001   山田太郎  45        70
2 1002   田中花子  32        52
3 1003   佐藤次郎  67        82
4 1005   高橋健太  51        55
```
`merge()`関数はデフォルトで内部結合を行います。両方のデータフレームに存在するレコードのみを返します。id 1004(鈴木美咲)は体重データがないため除外され、id 1006は患者データがないため除外されています。
### 3. 左外部結合(Left Join)
```r
left_result <- merge(patients, weights, by = "id", all.x = TRUE)
```
```
> print(left_result)
    id     name age weight_kg
1 1001   山田太郎  45        70
2 1002   田中花子  32        52
3 1003   佐藤次郎  67        82
4 1004   鈴木美咲  28        NA
5 1005   高橋健太  51        55
```
`all.x = TRUE`を指定すると、左側のデータフレーム(patients)のすべてのレコードを保持します。id 1004(鈴木美咲)の体重データがないため、weight_kgにはNAが入ります。
### 4. 右外部結合(Right Join)
```r
right_result <- merge(patients, weights, by = "id", all.y = TRUE)
```
```
> print(right_result)
    id     name age weight_kg
1 1001   山田太郎  45        70
2 1002   田中花子  32        52
3 1003   佐藤次郎  67        82
4 1005   高橋健太  51        55
5 1006     <NA>  NA        75
```
`all.y = TRUE`を指定すると、右側のデータフレーム(weights)のすべてのレコードを保持します。id 1006は患者データがないため、nameとageにはNAが入ります。
### 5. 完全外部結合(Full Join)
```r
full_result <- merge(patients, weights, by = "id", all = TRUE)
```
```
> print(full_result)
    id     name age weight_kg
1 1001   山田太郎  45        70
2 1002   田中花子  32        52
3 1003   佐藤次郎  67        82
4 1004   鈴木美咲  28        NA
5 1005   高橋健太  51        55
6 1006     <NA>  NA        75
```
`all = TRUE`を指定すると、両方のデータフレームのすべてのレコードを保持します。id 1004とid 1006の両方が含まれ、欠損している部分にはNAが入ります。
## merge()関数のパラメータまとめ
| パラメータ | 説明 | 結合タイプ |
|-----------|------|----------|
| デフォルト | 両方に存在するレコードのみ | 内部結合 |
| `all.x = TRUE` | 左側の全レコードを保持 | 左外部結合 |
| `all.y = TRUE` | 右側の全レコードを保持 | 右外部結合 |
| `all = TRUE` | 両方の全レコードを保持 | 完全外部結合 |
## まとめ
base Rの`merge()`関数を使うと、追加パッケージをインストールすることなくデータ結合を行うことができます。パラメータ名(`all.x`、`all.y`、`all`)も直感的で理解しやすいため、初心者にとって取り組みやすい方法です。
データ分析の現場では、データの欠損パターンや分析の目的に応じて適切な結合方法を選択することが重要です:
- **内部結合**: 完全なデータペアのみが必要な場合
- **左外部結合**: 主テーブルのすべてのレコードを保持したい場合
- **右外部結合**: 副テーブルのすべてのレコードを保持したい場合
- **完全外部結合**: 両方のテーブルのすべての情報を保持したい場合
実際の医療データ分析では、患者の基本情報と検査結果、投薬記録などを結合する際に、これらの操作を頻繁に使用します。
より発展的な方法として、tidyverseパッケージの`left_join()`、`inner_join()`などの関数もあります。これらはパイプ演算子(`%>%`)と組み合わせて使うことで、複雑なデータ処理をより読みやすく記述できます。詳しくは[[R - データ結合(tidyverse)]]を参照してください。