Python環境を起動中... 初回のみ数秒かかります
Lesson 11 / 12

テーブルの結合

このレッスンで学ぶこと

  • 2つのテーブルを共通のキーで結合できる(merge
  • 結合の種類(inner / left / right / outer)の違いを理解できる
  • テーブルを縦・横に連結できる(concat
  • 複数のデータを1つにまとめて分析できる

1. 複数のテーブルを1つにまとめる

実務のデータは、1つの表にすべてが揃っているとは限りません。 「患者基本情報テーブル(氏名・年齢)」と「検査結果テーブル(SBP・BMI)」が 別々に管理されている、というのはよくあることです。

分析するには、これらを患者IDなどの共通のキーでつなぎ合わせて1つの表にする必要があります。 pandasには、そのための2つの方法があります。

2. merge — キーでテーブルをつなぐ

pd.merge(左の表, 右の表, on="共通の列") で、 2つのテーブルを共通のキーでつなぎ合わせられます。 SQLを知っている方は「JOIN」と同じ操作だと考えてください。

sample_1.py
Ctrl+Enter
出力

💡 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)
sample_2.py
Ctrl+Enter
出力

🩺 医療データ文脈: 「全患者を残したいが、検査を受けていない人はSBPを空欄にしたい」場合は how="left"、 「検査も基本情報も揃っている患者だけ分析したい」場合は how="inner" を選びます。 どの行を残すかは分析の目的次第。leftで残った欠損は、レッスン7の欠損値処理で対応できます。

rightleft の左右を入れ替えただけ(左右の表を逆に書けば left で代用できる)、 outer は「どちらの表の患者も1人も漏らさず見たい」ときに使います。 まずは inner と left の2つを確実に押さえれば、実務のほとんどに対応できます。

4. concat — テーブルを積み重ねる

pd.concat([表1, 表2]) は、テーブルを縦に積み重ねます(行を増やす)。 「先月のデータ」と「今月のデータ」のように、同じ形式の表をつなげて1つにするのに使います。

sample_3.py
Ctrl+Enter
出力

💡 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. 練習問題

問題 1

2つのテーブルをmergeしよう

下記の info(基本情報)と labs(検査結果)を、患者IDをキーにmergeして表示してください。

exercise_1.py
出力
ヒントを見る(答え+解説)
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つの表にまとまります。

問題 2

leftで全患者を残そう

下記で、info(全患者)を残すように how="left" でmergeしてください。 検査が無いP003はSBPがNaNになるはずです。

exercise_2.py
出力
ヒントを見る(答え+解説)
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(欠損)になります。「全患者を母数にしたい」分析でよく使います。

問題 3

2つの表をconcatで縦に積もう

下記の day1day2 を、concat縦に積み重ねて(indexは振り直して)表示してください。

exercise_3.py
出力
ヒントを見る(答え+解説)
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の欠損値処理で対応できる

自由に試してみましょう:

free_practice.py
出力

完了するとコース一覧に進捗が記録されます