1. 複数のテーブルを1つにまとめる
実務のデータは、1つの表にすべてが揃っているとは限りません。 「患者基本情報テーブル(氏名・年齢)」と「検査結果テーブル(SBP・BMI)」が 別々に管理されている、というのはよくあることです。
分析するには、これらを患者IDなどの共通のキーでつなぎ合わせて1つの表にする必要があります。 pandasには、そのための2つの方法があります。
- merge … 共通のキー(患者IDなど)で横につなぐ(列を増やす)
- concat … テーブルを縦に積む(行を増やす)/ 横に並べる
2. merge — キーでテーブルをつなぐ
pd.merge(左の表, 右の表, on="共通の列") で、
2つのテーブルを共通のキーでつなぎ合わせられます。
SQLを知っている方は「JOIN」と同じ操作だと考えてください。
💡 mergeの仕組み:
on="患者ID" は「この列の値が一致する行どうしをつなぐ」という指定です。
info の P001 と labs の P001 が同じ患者IDなので、その行の情報(氏名とSBP・BMI)が横一列にまとまります。
バラバラに管理されたデータを、IDで照合して1つにする——これがmergeの役割です。
3. 結合の種類(inner / left / right / outer)
2つのテーブルでキーが完全に一致しない場合、どの行を残すかを how で指定します。
how には4種類あり、なかでも実務でよく使うのが inner(両方にある行だけ)と left(左の表は全部残す)です。
| how | 残る行 |
|---|---|
inner(デフォルト) | 両方のテーブルにあるキーの行だけ |
left | 左の表の行はすべて残す(右に無ければNaN) |
right | 右の表の行はすべて残す(left の左右を入れ替えたもの) |
outer | どちらか一方にでもあるキーは全部残す(足りない側はNaN) |
🩺 医療データ文脈:
「全患者を残したいが、検査を受けていない人はSBPを空欄にしたい」場合は how="left"、
「検査も基本情報も揃っている患者だけ分析したい」場合は how="inner" を選びます。
どの行を残すかは分析の目的次第。leftで残った欠損は、レッスン7の欠損値処理で対応できます。
right は left の左右を入れ替えただけ(左右の表を逆に書けば left で代用できる)、
outer は「どちらの表の患者も1人も漏らさず見たい」ときに使います。
まずは inner と left の2つを確実に押さえれば、実務のほとんどに対応できます。
4. concat — テーブルを積み重ねる
pd.concat([表1, 表2]) は、テーブルを縦に積み重ねます(行を増やす)。
「先月のデータ」と「今月のデータ」のように、同じ形式の表をつなげて1つにするのに使います。
💡 ignore_index=True でindexを振り直す:
concat をそのまま使うと、元のindex(0,1 と 0,1)がそのまま残り重複します。
ignore_index=True を付けると、連結後に 0,1,2,3 と通し番号を振り直してくれます。
縦に積むときはこれを付けるのが定番です。
💡 merge と concat の使い分け:
- 列を増やす(情報を横につなぐ)→
merge(キーで照合) - 行を増やす(同じ形式のデータをつなげる)→
concat
「別々の情報を1人にひも付ける=merge」「同じ種類のデータを集める=concat」と覚えましょう。
5. 練習問題
2つのテーブルをmergeしよう
下記の info(基本情報)と labs(検査結果)を、患者IDをキーにmergeして表示してください。
ヒントを見る(答え+解説)
import pandas as pd
info = pd.DataFrame({
"患者ID": ["P001", "P002", "P003"],
"年齢": [45, 62, 33],
})
labs = pd.DataFrame({
"患者ID": ["P001", "P002", "P003"],
"BMI": [22.5, 28.1, 24.0],
})
# 患者IDをキーに merge して表示してください
print(pd.merge(info, labs, on="患者ID"))
# 患者ID・年齢・BMI が1つの表にまとまる
pd.merge(info, labs, on="患者ID") で、患者IDが一致する行どうしを横につなぎます。年齢とBMIが1つの表にまとまります。
leftで全患者を残そう
下記で、info(全患者)を残すように how="left" でmergeしてください。
検査が無いP003はSBPがNaNになるはずです。
ヒントを見る(答え+解説)
import pandas as pd
info = pd.DataFrame({
"患者ID": ["P001", "P002", "P003"],
"氏名": ["田中", "佐藤", "鈴木"],
})
labs = pd.DataFrame({
"患者ID": ["P001", "P002"],
"SBP": [120, 145],
})
# how="left" で全患者を残して merge してください
merged = pd.merge(info, labs, on="患者ID", how="left")
print(merged)
# P003 の SBP は NaN(検査データが無いため)
how="left" は左の表(info)の行をすべて残します。P003は検査結果が無いので、SBPがNaN(欠損)になります。「全患者を母数にしたい」分析でよく使います。
2つの表をconcatで縦に積もう
下記の day1 と day2 を、concat で縦に積み重ねて(indexは振り直して)表示してください。
ヒントを見る(答え+解説)
import pandas as pd
day1 = pd.DataFrame({"患者ID": ["P001","P002"], "SBP": [120, 145]})
day2 = pd.DataFrame({"患者ID": ["P003","P004"], "SBP": [130, 138]})
# 縦に積み重ねて(ignore_index=True で)表示してください
combined = pd.concat([day1, day2], ignore_index=True)
print(combined)
# 4行(P001〜P004)にまとまり、indexは0〜3
pd.concat([day1, day2], ignore_index=True) で、2つの表を縦に積んで4行の表にできます。ignore_index=True でindexが0〜3に振り直されます。同じ形式のデータを集約する定番です。
6. まとめ
このレッスンのポイント
pd.merge(左, 右, on="キー"):共通のキーで横につなぐ(列を増やす)how=で結合の種類を指定:inner(共通のみ)/left(左を全部)/right(右を全部)/outer(全件)pd.concat([表1, 表2], ignore_index=True):縦に積む(行を増やす)- 列を増やす=merge、行を増やす=concat
- leftで生じた欠損は、レッスン7の欠損値処理で対応できる
自由に試してみましょう:
完了するとコース一覧に進捗が記録されます