Python | データ処理:pandas の join

Python
スポンサーリンク

概要(pandas の join は「インデックスで横に結合」する最短ルート)

DataFrame.join は、“インデックス”をキーにして横方向(列を増やす)へ結合します。SQL の JOIN に似ていますが、基本は「インデックス同士を合わせる」点が違いです。最重要ポイントは「インデックスを整える」「how(left/inner/outer/right)を選ぶ」「列名の衝突に備える(suffix)」「型を一致させる」。これだけで、意図通りに安全な結合ができます。


基本(join の考え方と最小例)

最小例(共通インデックスで横に結合)

import pandas as pd

df1 = pd.DataFrame({"A": [10, 20, 30]}, index=[1, 2, 3])
df2 = pd.DataFrame({"B": [100, 200, 300]}, index=[2, 3, 4])

out = df1.join(df2)  # デフォルトは how="left"
print(out)
# index: 1,2,3 が基準。2,3 は B が付き、1 は B が欠損、4 は捨てられる
Python

join は左側の DataFrame のインデックスを基準に結合します。合わないものは欠損(NaN)になります。

列をキーにして結合(左は列で、右はインデックス)

left  = pd.DataFrame({"id":[1,2,3], "A":[10,20,30]})
right = pd.DataFrame({"B":[100,200,300]}, index=[1,2,4])  # 右は index がキー

out = left.join(right, on="id")  # 左は列 "id"、右は index
print(out)
Python

on を使うと「左は指定列、右はインデックス」で結合できます。右側も列で結合したいときは set_index で整えます。


結合方法の選び方(left/inner/outer/right の違い)

how の意味(抜けと重なりをどう扱うか)

df1 = pd.DataFrame({"A":[10,20,30]}, index=[1,2,3])
df2 = pd.DataFrame({"B":[100,200,300]}, index=[2,3,4])

print(df1.join(df2, how="left"))   # 左の index を残す(1,2,3)
print(df1.join(df2, how="inner"))  # 共通のみ(2,3)
print(df1.join(df2, how="outer"))  # 全部(1,2,3,4)
print(df1.join(df2, how="right"))  # 右の index を残す(2,3,4)
Python
  • left(デフォルト):レポート基準が左にあるときの定番
  • inner:両方に存在するキーのみ(分析で“共通部分だけ”比較)
  • outer:抜けを許して“全量俯瞰”
  • right:右を基準(左の代わりに右を軸にしたいとき)

インデックスを整える(set_index と on の使い分け)

右も列で結合したいなら両方 set_index

left  = pd.DataFrame({"id":[1,2,3], "A":[10,20,30]})
right = pd.DataFrame({"id":[2,3,4], "B":[100,200,300]})

out = left.set_index("id").join(right.set_index("id"), how="left").reset_index()
print(out)
Python

両方のキーが列にあるなら、先に set_index してから join が最短です。終わったら reset_index で元に戻します。

複合キー(複数列)で結合する

left  = pd.DataFrame({"store":["A","A","B"], "month":["Jan","Feb","Jan"], "sales":[100,120,90]})
right = pd.DataFrame({"store":["A","B"], "month":["Jan","Jan"], "target":[110,95]})

out = left.set_index(["store","month"]).join(
      right.set_index(["store","month"]), how="left").reset_index()
print(out)
Python

複数列をキーにしたいときも「set_index(複数列)→join」が読みやすく安全です。


複数 DataFrame の同時結合と列名衝突(lsuffix/rsuffix)

まとめて 2 つ以上を結合する

base = pd.DataFrame({"A":[1,2,3]}, index=[1,2,3])
d1   = pd.DataFrame({"B":[10,20,30]}, index=[1,3,4])
d2   = pd.DataFrame({"C":[100,200,300]}, index=[2,3,5])

out = base.join([d1, d2], how="outer")
print(out)
Python

リストで渡すと、一度に複数を結合できます。基準は最初の DataFrame のインデックスです。

列名が重なるときはサフィックスで解決

df1 = pd.DataFrame({"val":[1,2,3]}, index=[1,2,3])
df2 = pd.DataFrame({"val":[10,20,30]}, index=[2,3,4])

out = df1.join(df2, how="outer", lsuffix="_left", rsuffix="_right")
print(out)
Python

同名列があるとエラーや上書きの原因になります。lsuffix/rsuffix で衝突を回避します。


時系列・カテゴリの実践例(整列→結合が品質を決める)

時系列のリサンプル後に join(粒度を揃える)

import pandas as pd

sales = pd.Series([100,120,80], index=pd.to_datetime(["2025-01-01","2025-01-02","2025-01-04"]))
users = pd.Series([50,60,55],   index=pd.to_datetime(["2025-01-01","2025-01-03","2025-01-04"]))

# 日次に揃えてから結合
s_daily = sales.resample("D").sum()
u_daily = users.resample("D").sum()

out = s_daily.to_frame("sales").join(u_daily.to_frame("users"), how="outer")
print(out)
Python

頻度を揃えずに join するとズレます。resample などで“比較可能な軸”へ整えてから結合します。

マスタ結合(コード→名前)で可読化

facts = pd.DataFrame({"store_id":[1,2,1], "sales":[100,120,90]})
master = pd.DataFrame({"store_id":[1,2], "store_name":["Tokyo","Osaka"]})

out = facts.set_index("store_id").join(master.set_index("store_id"), how="left").reset_index()
print(out)
Python

ID と名称の突き合わせは join の王道。キーの型一致(int/str)に注意します。


つまずき対策(重複インデックス・欠損・型の一致・sort・mergeとの使い分け)

重複インデックスは“多対多結合”になる

左や右のキーが重複していると、行が増えます(直積的に結合)。意図なら OK、そうでなければ事前に drop_duplicates でユニーク化します。

欠損は NaN になる(後工程で埋めるか落とす)

outer/left/right では欠損が出ます。fillna で埋めるか、必要に応じて欠損行を除外します。

型を揃える(int と str の不一致は結合不能)

キーの dtype が違うと合流しません。astype で一致させてから結合します。

sort は結果の順序を整えるだけ

join(sort=True) は結合後のインデックスをソートします。計算結果は変わらないので、見やすさのために使います。

merge との使い分け

  • join:インデックス基準で横結合(時系列・主キーが index にあるとき最短)
  • merge:列基準で柔軟に結合(on/left_on/right_on、複雑なキー指定に強い) 列キーでの結合が複雑なら merge、インデックス基準で短く書けるなら join。

まとめ(「インデックスをキーに整える→how を選ぶ→衝突と型を管理」で意図通りに結合)

pandas の join は、インデックスを基準に横方向へ結合する最短手段です。set_index でキーを揃え、how で欠損・抜けの扱いを決め、lsuffix/rsuffix で列名衝突を避け、dtype を一致させる。複数 DataFrame も一度に結合でき、時系列は頻度整形→join が鉄板。列基準の柔軟な結合が必要なら merge を選ぶ。これらの型を守れば、初心者でも“短くて安全”な結合処理が安定して書けます。

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