0Pricing
Pandas & NumPy Academy · レッスン

pd.merge:内部結合と外部結合

共通のキー列を使って2つのDataFrameを内部結合または外部結合し、どの行が保持・削除されるかを理解します。

「pd.merge:内部結合と外部結合」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

Join とは

join は、共通のキー列に基づいて行を照合し、2 つの DataFrame を結合します。これは SQL の JOIN 句と同じ考え方です。Pandas では pd.merge() を使って join を実行します。単にデータを積み重ねる pd.concat() とは異なり、pd.merge() は、1 つ以上の列の値が一致するかどうかに基づいて、異なる 2 つのテーブルの行を適切に対応付けます。

共通のキー列

merge を実行するには、両方の DataFrame に共通する値を持つ列が少なくとも 1 つ必要です。これをキー列と呼びます。たとえば、orders テーブルに customer_id 列があり、customers テーブルにも customer_id 列があるとします。customer_id をキーにして merge すると、各注文行に顧客情報が追加されます。両方の DataFrame で列名が同じ場合は、on パラメータでキーを指定します。

import pandas as pd

orders = pd.DataFrame({
    'order_id': [1, 2, 3, 4],
    'customer_id': [101, 102, 101, 103],
    'amount': [250, 80, 320, 150]
})

customers = pd.DataFrame({
    'customer_id': [101, 102, 104],
    'name': ['Alice', 'Bob', 'Diana']
})

Inner Join:両テーブルの共通部分

inner join(デフォルト)は、キーの値が両方の DataFrame に存在する行だけを残します。どちらか一方のテーブルにしか存在せず、もう一方に一致するキーがない行は、何も通知されずに削除されます。orders の例では、customer 103 と 104 はもう一方のテーブルに一致する行がないため、inner join の結果から除外されます。

# Inner join (default): only matching rows from both
result = pd.merge(orders, customers, on='customer_id', how='inner')
print(result)
#    order_id  customer_id  amount   name
# 0         1          101     250  Alice
# 1         3          101     320  Alice
# 2         2          102      80    Bob
# Order 4 (customer 103) dropped - no match in customers
# Diana (customer 104) dropped - no match in orders

Outer Join:両テーブルの和集合

outer join(how='outer')は、両方の DataFrame からすべての行を残します。もう一方のテーブルに一致するキーがない行では、不足している列が NaN で埋められます。これは、片方のデータセットで一致しなかったレコードも保持し、両方のデータセットを完全に把握したい場合に便利です。

result = pd.merge(orders, customers, on='customer_id', how='outer')
print(result)
#    order_id  customer_id  amount   name
# 0       1.0          101   250.0  Alice
# 1       3.0          101   320.0  Alice
# 2       2.0          102    80.0    Bob
# 3       4.0          103   150.0    NaN  <- order with unknown customer
# 4       NaN          104     NaN  Diana  <- customer with no orders

異なる名前の列を使った Merge

各 DataFrame でキー列の名前が異なる場合は、on の代わりに left_on と right_on を使います。Pandas は、左側の DataFrame の left_on と右側の DataFrame の right_on が等しい行を照合します。結果には両方のキー列が含まれるため、不要な方は後から削除できます。

products = pd.DataFrame({
    'prod_id': [10, 20, 30],
    'name': ['Widget', 'Gadget', 'Doohickey']
})

order_lines = pd.DataFrame({
    'item_id': [10, 10, 20],
    'qty': [3, 1, 5]
})

result = pd.merge(order_lines, products,
                  left_on='item_id', right_on='prod_id')
print(result.drop(columns='prod_id'))
#    item_id  qty    name
# 0       10    3  Widget
# 1       10    1  Widget
# 2       20    5  Gadget

複数の列を使った Merge

列の組み合わせ(複合キー)で行を照合するには、on にリストを渡します。これは、1 つの列だけでは一意に照合できない場合によく使われます。たとえば、year と region の両方をキーにして merge できます。結果に含めるには、指定したすべての列が同時に一致する必要があります。

targets = pd.DataFrame({
    'year': [2023, 2023, 2024],
    'region': ['East', 'West', 'East'],
    'target': [100, 150, 120]
})
actuals = pd.DataFrame({
    'year': [2023, 2024, 2024],
    'region': ['East', 'East', 'West'],
    'actual': [95, 115, 80]
})

result = pd.merge(targets, actuals, on=['year', 'region'], how='inner')
print(result)
#    year region  target  actual
# 0  2023   East     100      95
# 1  2024   East     120     115

重複する列名の扱い

両方の DataFrame に、キー以外で同じ名前の列がある場合、Pandas は区別できるようにサフィックスを付けます。デフォルトでは、左側に _x、右側に _y が付きます。suffixes パラメータでこれらを変更し、より意味のある名前にして結果の混乱を避けることができます。

df_a = pd.DataFrame({'id': [1, 2], 'value': [10, 20]})
df_b = pd.DataFrame({'id': [1, 2], 'value': [100, 200]})

# Default suffixes
print(pd.merge(df_a, df_b, on='id'))
#    id  value_x  value_y

# Custom suffixes
print(pd.merge(df_a, df_b, on='id', suffixes=('_budget', '_actual')))
#    id  value_budget  value_actual

予期しない重複の確認

merge でよくある問題は、予期しない行の増加です。両方の DataFrame のキー列に重複値があると、merge によって一致するすべての行の直積が生成されます。merge 後は必ず行数を確認してください。想定より多い場合は、df.duplicated(subset=['key']).sum() を使ってキー列の重複を調べます。

# Both tables have duplicate keys -> cartesian product
left = pd.DataFrame({'id': [1, 1], 'val_l': ['a', 'b']})
right = pd.DataFrame({'id': [1, 1], 'val_r': ['x', 'y']})

result = pd.merge(left, right, on='id')
print(len(result))  # 4 rows! (2x2 cartesian product)
print(result)
#    id val_l val_r
# 0   1     a     x
# 1   1     a     y
# 2   1     b     x
# 3   1     b     y

安全性を高める validate パラメータ

validate パラメータを渡すと、merge における関係の制約を適用し、制約に違反した場合にエラーを発生させられます。'one_to_one' は両方のテーブルでキーが一意であることを要求し、'one_to_many' は左側のテーブルだけでキーが一意であることを要求し、'many_to_one' は右側のテーブルだけでキーが一意であることを要求します。これは、データ品質の問題を早期に検出できる優れた防御的コーディング手法です。

# Safe merge: validate that customer_id is unique in customers
try:
    result = pd.merge(orders, customers,
                      on='customer_id',
                      how='inner',
                      validate='many_to_one')
    print('Merge OK, shape:', result.shape)
except Exception as e:
    print('Merge error:', e)

indicator による対応状況の確認

indicator=True を渡すと、各行がどこから来たかを示す _merge 列が結果に追加されます。値は 'left_only'、'right_only'、'both' のいずれかです。これは outer join の後に、一致したレコードと一致しなかったレコードを特定するのに便利です。_merge 列を削除する前に、データ品質を監査できます。

result = pd.merge(orders, customers, on='customer_id',
                  how='outer', indicator=True)
print(result['_merge'].value_counts())
# both           3
# left_only      1  <- orders with no customer record
# right_only     1  <- customers with no orders

# Find unmatched orders
print(result[result['_merge'] == 'left_only'])

Inner と Outer のまとめ

2 種類の join をまとめると、inner join は共通部分、つまり両方の DataFrame でキーが一致する行だけを返します。outer join は和集合、つまり両方の DataFrame のすべての行を返し、一致しない部分は NaN になります。補足すると、left join は左側の DataFrame のすべての行を保持し、right join は右側の DataFrame のすべての行を保持します。これらについては次のレッスンで扱います。

# Quick reference
# how='inner'  -> intersection: only matched rows
# how='outer'  -> union: all rows from both, NaN for no match
# how='left'   -> all left rows + matched right rows
# how='right'  -> all right rows + matched left rows

# Most common: inner (default) for enrichment, left for preserving records

理解度チェック

このレッスンで学んだ pd.merge の inner join と outer join の理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、how='inner' を指定した pd.merge() は両方の DataFrame から一致する行だけを残し、how='outer' は一致しない部分を NaN にしてすべての行を残すこと、on は共通のキーを指定し、left_on/right_on は列名が異なる場合に使うこと、そして indicator パラメータでどの行が一致したかを確認できることを学びました。次は、一方の側のすべての行を保持する left join と right join について学びます。

よくある質問

「pd.merge:内部結合と外部結合」レッスンは無料ですか?

はい。「pd.merge:内部結合と外部結合」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「pd.merge:内部結合と外部結合」で何を学びますか?

共通のキー列を使って2つのDataFrameを内部結合または外部結合し、どの行が保持・削除されるかを理解します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「pd.merge:内部結合と外部結合」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. DataFrameの結合に使うpd.concat
  2. pd.merge:内部結合と外部結合
  3. 左結合と右結合
  4. インデックスによる結合
← Pandas & NumPy Academyに戻る