pandas merge()の使い方|inner・left・outerの違いと行数が増える原因を解説

Pandasで顧客表と購入表のような2つのDataFrameを結合するときは、merge()を使います。ただし、コードがエラーなく動いても、結合方法を誤ると必要な行が消えたり、重複キーによって行数が増えたりします。

この記事では、どの行を残したいかからinner・left・outerを選び、結合後に結果を確認する方法を解説します。

この記事でわかること

  • pandas merge()で2つのDataFrameを共通キーで結合する基本
  • inner・left・outerを、残したい行から選ぶ方法
  • 行数が増える理由と、validateによる確認方法
  • NaN・未一致の行をindicator=Trueで確認する方法
  • concat()・join()との使い分けと、結合後の集計への進み方

先に結論:残したい行で結合方法を選ぶ

目的選ぶ方法結果で最初に見る点
両方の表にあるデータだけを使うhow="inner"一致しない行が落ちていないか
左側の表を基準に情報を追加するhow="left"右側の列のNaNと行数
両方の表にしかないデータも確認するhow="outer"left_only・right_onlyの行

顧客一覧を基準に購入情報を追加するならleft結合が自然です。結合後は、行数・結合キー・右側の列のNaNを必ず確認してください。

サンプル:顧客表と購入表を用意する

顧客表の顧客IDをキーに購入表を結合します。ID 102には購入履歴が2件、ID 104には購入履歴がなく、購入表には顧客表にないID 105があります。

import pandas as pd

customers = pd.DataFrame({
    "顧客ID": [101, 102, 103, 104],
    "顧客名": ["青木", "井上", "上田", "遠藤"],
    "会員区分": ["一般", "一般", "プレミアム", "一般"]
})

orders = pd.DataFrame({
    "顧客ID": [101, 102, 102, 105],
    "注文ID": ["A001", "A002", "A003", "A004"],
    "購入額": [1200, 2500, 800, 1800]
})

print("顧客表")
display(customers)
print("購入表")
display(orders)
print(f"顧客表の行数: {len(customers)}行、購入表の行数: {len(orders)}行")
顧客ID顧客名会員区分
0101青木一般
1102井上一般
2103上田プレミアム
3104遠藤一般
顧客ID注文ID購入額
0101A0011200
1102A0022500
2102A003800
3105A0041800

顧客表と購入表は各4行ですが、購入表ではID 102が2回あります。この重複が結合後の行数に影響します。

merge()の基本形:共通の列をキーに結合する

同じ名前のキー列がある場合は、on="顧客ID"と明示します。howを省略した場合はinner結合です。

inner_result = customers.merge(orders, on="顧客ID", how="inner")
display(inner_result)
print(f"inner結合後の行数: {len(inner_result)}行")
顧客ID顧客名会員区分注文ID購入額
0101青木一般A0011200
1102井上一般A0022500
2102井上一般A003800

inner結合では、両方の表にあるID 101・102だけが残ります。ID 102は購入履歴が2件あるため2行になります。ID 103・104・105は出力から消えるため、購入していない顧客も分析したい場合には向きません。

left結合:顧客表を残したまま購入情報を追加する

left_result = customers.merge(orders, on="顧客ID", how="left")
display(left_result)
print(f"結合前の顧客表: {len(customers)}行")
print(f"left結合後: {len(left_result)}行")
顧客ID顧客名会員区分注文ID購入額
0101青木一般A0011200.0
1102井上一般A0022500.0
2102井上一般A003800.0
3103上田プレミアムNaNNaN
4104遠藤一般NaNNaN

ID 103・104は購入表にないため、右側の列がNaNになります。これはエラーではなく、右表に対応する行がなかった結果です。一方、ID 102は2件の注文に対応するため、left結合後は5行になります。

outer結合:未一致の行も含めて確認する

outer_result = customers.merge(
    orders,
    on="顧客ID",
    how="outer",
    indicator=True
)
display(outer_result)
display(outer_result["_merge"].value_counts())
顧客ID顧客名会員区分注文ID購入額_merge
0101青木一般A0011200.0both
1102井上一般A0022500.0both
2102井上一般A003800.0both
3103上田プレミアムNaNNaNleft_only
4104遠藤一般NaNNaNleft_only
5105NaNNaNA0041800.0right_only
count
both3
left_only2
right_only1

_mergeがbothなら一致、left_onlyなら左表だけ、right_onlyなら右表だけにあるキーです。NaNを埋めたり行を除外したりする前に、未一致の理由を確認します。

行数が増える原因:重複したキーが組み合わさる

merge()後の行数が増える主な理由は、結合キーが片側または両側で重複していることです。注文表では同じ顧客が複数回購入するため、ID 102が2行あります。これは顧客1人に注文が複数ある1対多の関係です。

print("顧客表で重複している顧客ID")
display(customers[customers["顧客ID"].duplicated(keep=False)])

print("購入表で重複している顧客ID")
display(orders[orders["顧客ID"].duplicated(keep=False)].sort_values("顧客ID"))

print("顧客IDごとの注文件数")
display(orders["顧客ID"].value_counts().sort_index())

結合前にキー列のduplicated()とvalue_counts()を確認し、行数増加が想定内かをデータの意味から判断してください。

validateで想定外の重複キーを早く見つける

注文表から顧客表へ情報を追加する場合、注文は重複してよく、顧客表の顧客IDは一意であるべきです。この関係はmany_to_oneで検証できます。

orders_with_customer = orders.merge(
    customers,
    on="顧客ID",
    how="left",
    validate="many_to_one",
    indicator=True
)
display(orders_with_customer)
print(f"注文表と結合結果の行数: {len(orders)}行 → {len(orders_with_customer)}行")
想定する対応関係validateの値例
左右ともキーが一意one_to_one社員番号と社員属性
左は重複可、右は一意many_to_one複数注文と顧客マスタ
左は一意、右は重複可one_to_many顧客マスタと複数注文
customers_with_duplicate = pd.concat([
    customers,
    customers.loc[[1]]
], ignore_index=True)

try:
    orders.merge(
        customers_with_duplicate,
        on="顧客ID",
        how="left",
        validate="many_to_one"
    )
except pd.errors.MergeError as error:
    print("確認が必要な結合です:")
    print(error)

display(customers_with_duplicate[customers_with_duplicate["顧客ID"].duplicated(keep=False)])

MergeErrorが出たときの直し方

  • 現象:validate="many_to_one"でMergeErrorが出る。
  • 原因:右側の顧客表に同じ顧客IDが複数あり、一意ではない。
  • 確認方法:duplicated(keep=False)で重複行を表示する。
  • 修正方法:誤った重複なら原因を確認してから除き、意味のある複数行なら結合目的を見直す。
  • 修正後:もう一度validateを指定し、行数と結果を確認する。

列名が違うときはleft_onとright_onを使う

orders_english_key = orders.rename(columns={"顧客ID": "customer_id"})
different_key_result = customers.merge(
    orders_english_key,
    left_on="顧客ID",
    right_on="customer_id",
    how="left"
)
display(different_key_result)

列名が違うだけでなく、文字列と数値が混在している、前後に空白がある状態でも一致しない行が出ます。結合前にdtypes、isna()、str.strip()が必要かを確認してください。

コードは動くのに合わないとき:キーの型と空白を確認する

orders_dirty_key = pd.DataFrame({
    "顧客ID": ["101", "102", " 103 "],
    "注文ID": ["B001", "B002", "B003"]
})

customers_text_key = customers.copy()
customers_text_key["顧客ID"] = customers_text_key["顧客ID"].astype(str)

before_fix = customers_text_key.merge(orders_dirty_key, on="顧客ID", how="left")
print("修正前:ID 103は一致しません")
display(before_fix)

orders_dirty_key["顧客ID"] = orders_dirty_key["顧客ID"].str.strip()
after_fix = customers_text_key.merge(orders_dirty_key, on="顧客ID", how="left")
print("修正後:ID 103も一致します")
display(after_fix)

pandasでは、左右のキーがどちらも欠損値の行が一致として結合されることがあります。SQLと同じだと思い込まず、結合前にキー列のisna()を確認し、欠損行を残すか除くかをデータの意味から決めてください。

merge()・concat()・join()の使い分け

手法何をしたいか選ぶ場面注意点
merge()共通キーで別表の列を対応付ける顧客表へ購入表の列を追加するキーと対応関係を確認する
concat()同じ構造の表を積み重ねる月別CSVを上下にまとめるキー照合はしない
join()主にインデックスを基準に結合するインデックスがそろった表を結合するキー列ならmerge()が読みやすい

結合後は集計・可視化へ進む

matched_orders = orders_with_customer.query("_merge == 'both'")
customer_sales = (
    matched_orders.groupby("顧客名", as_index=False)["購入額"]
    .sum()
    .sort_values("購入額", ascending=False)
)
display(customer_sales)
顧客名購入額
0井上3300
1青木1200

結合で顧客名を追加してからgroupby()で購入額を集計できます。未一致や行数を確認する前に集計へ進まないことが大切です。

自分のデータへ置き換える前のチェックリスト

  • 左表と右表のどちらを基準に残すか決めたか
  • 結合キーは同じ意味で、列名・型・前後空白がそろっているか
  • キーの重複は想定どおりか
  • 結合後に想定する行数を説明できるか
  • indicator=Trueで未一致行を確認したか
  • NaNを埋める前に、未一致か元データの欠損かを確認したか

まとめ

  • merge()は、共通キーで別のDataFrameの列を対応付けるときに使う
  • 両方にある行だけならinner、左表を基準にするならleft、未一致も確認するならouterを選ぶ
  • 行数が増えたらキーの重複と対応関係を確認する
  • indicatorで未一致を、validateで想定外の重複を確認できる
  • 結合結果を確認してから集計・表の整形・可視化へ進む

関連記事

▲ ページトップへ戻る

pandas merge()で行数が増えるのはなぜですか?

結合キーが片側または両側で重複していると、同じキーの行どうしが組み合わさります。結合前にduplicated()とvalue_counts()で確認し、validateを指定します。

innerとleftはどちらを使えばよいですか?

両方の表にあるデータだけを使うならinner、左側の表をすべて残して右側の情報を追加するならleftです。

merge後にNaNが出るのはなぜですか?

left結合では、右表に同じキーがない行の右側列がNaNになります。indicator=Trueを使い、未一致か、キーの型や空白の違いかを確認してください。

結合キーの列名が違う場合はどうしますか?

left_onとright_onに、それぞれのキー列名を指定します。値の意味、型、前後空白も確認します。

validateでMergeErrorになったら何を確認しますか?

指定した対応関係と実データのキー重複が合っていません。左右のキー列をduplicated(keep=False)で表示し、重複の意味を確認します。

結合キーにNaNがあるとどうなりますか?

pandasでは左右とも欠損値のキーが一致として結合されることがあります。結合前にisna()で確認してください。

コメント

タイトルとURLをコピーしました