Pandas DataFrameの結合を極める!merge, joinでデータ統合 🤝
データ分析では、複数のデータソースから得られた情報を組み合わせて分析することが不可欠です。PandasのDataFrameも例外ではなく、異なるDataFrameを結合する機能はデータ統合の要となります。この結合操作の主役となるのが、merge()関数と**join()メソッド**です。これらの機能を使うことで、リレーショナルデータベースのように、共通のキー(列やインデックス)に基づいてDataFrameを横方向に連結できます。
この記事では、merge()とjoin()のそれぞれの特徴、基本的な使い方、そして様々な結合タイプ(内部結合、左結合、右結合、外部結合)について、具体的なコード例を交えながら詳しく解説します。
merge():SQLライクな結合の決定版 ✨
pd.merge()関数は、SQLのJOIN操作に最も似ており、一つ以上の共通の列(キー)に基づいてDataFrameを結合する際に非常に強力です。
基本的な結合(内部結合:how='inner')
merge()のデフォルトの結合タイプは**内部結合(inner)**です。これは、両方のDataFrameに共通して存在するキーのみを結合します。
import pandas as pd
# 顧客データ
customers_df = pd.DataFrame({
'customer_id': [1, 2, 3, 4],
'name': ['Alice', 'Bob', 'Charlie', 'David']
})
# 注文データ
orders_df = pd.DataFrame({
'order_id': [101, 102, 103, 104],
'customer_id': [1, 3, 2, 5], # customer_id=5 は customers_df にはない
'amount': [1000, 1500, 500, 2000]
})
print("--- 顧客データ ---")
print(customers_df)
print("\n--- 注文データ ---")
print(orders_df)
# customer_id をキーにして内部結合
merged_inner_df = pd.merge(customers_df, orders_df, on='customer_id', how='inner')
print("\n--- 内部結合 (inner merge) ---")
print(merged_inner_df)
# 出力例:
# customer_id name order_id amount
# 0 1 Alice 101 1000
# 1 2 Bob 103 500
# 2 3 Charlie 102 1500
on引数で、結合の基準となる列名を指定します。共通の列名が複数ある場合はリストで指定します(例: on=['key1', 'key2'])。
さまざまな結合タイプ (how引数) 🤝
how引数を使って、SQLのJOINタイプと同様に、結合の挙動を制御できます。
-
'inner'(内部結合): 両方のDataFrameに存在する共通のキーの行のみを結合します。 -
'left'(左結合): 左のDataFrameのすべての行を含め、右のDataFrameから一致するキーの行を結合します。一致しない場合はNaNが入ります。 -
'right'(右結合): 右のDataFrameのすべての行を含め、左のDataFrameから一致するキーの行を結合します。一致しない場合はNaNが入ります。 -
'outer'(外部結合): 両方のDataFrameのすべての行(共通するキーと、どちらか一方にのみ存在するキーの両方)を含めて結合します。一致しない場合はNaNが入ります。
import pandas as pd
df1 = pd.DataFrame({'key': ['A', 'B', 'C'], 'val1': [1, 2, 3]})
df2 = pd.DataFrame({'key': ['B', 'C', 'D'], 'val2': [4, 5, 6]})
print("--- df1 ---")
print(df1)
print("\n--- df2 ---")
print(df2)
# 左結合 (left merge)
merged_left_df = pd.merge(df1, df2, on='key', how='left')
print("\n--- 左結合 (left merge) ---")
print(merged_left_df)
# 出力例:
# key val1 val2
# 0 A 1 NaN
# 1 B 2 4.0
# 2 C 3 5.0
# 右結合 (right merge)
merged_right_df = pd.merge(df1, df2, on='key', how='right')
print("\n--- 右結合 (right merge) ---")
print(merged_right_df)
# 出力例:
# key val1 val2
# 0 B 2.0 4
# 1 C 3.0 5
# 2 D NaN 6
# 外部結合 (outer merge)
merged_outer_df = pd.merge(df1, df2, on='key', how='outer')
print("\n--- 外部結合 (outer merge) ---")
print(merged_outer_df)
# 出力例:
# key val1 val2
# 0 A 1.0 NaN
# 1 B 2.0 4.0
# 2 C 3.0 5.0
# 3 D NaN 6.0
異なる列名で結合する (left_on, right_on)
結合キーとなる列名が左右のDataFrameで異なる場合、left_onとright_onを使ってそれぞれ指定します。
import pandas as pd
df_users = pd.DataFrame({
'user_id': [1, 2],
'name': ['Alice', 'Bob']
})
df_activities = pd.DataFrame({
'person_id': [1, 3], # 列名が異なる
'activity': ['Login', 'Logout']
})
# user_id と person_id を使って結合
merged_diff_cols = pd.merge(df_users, df_activities, left_on='user_id', right_on='person_id', how='left')
print("\n--- 異なる列名で結合 ---")
print(merged_diff_cols)
join():インデックス基準の結合に特化 🔗
DataFrameのjoin()メソッドは、インデックス(行ラベル)に基づいてDataFrameを結合する際に特に便利です。merge()でもインデックス結合は可能ですが、join()の方がより簡潔に記述できます。
基本的な結合(インデックス同士の結合)
join()のデフォルトは左結合(how='left')です。
import pandas as pd
df_price = pd.DataFrame({
'price': [100, 150, 200]
}, index=['Apple', 'Banana', 'Cherry']) # 商品名をインデックスに
df_stock = pd.DataFrame({
'stock': [50, 120, 30]
}, index=['Banana', 'Apple', 'Orange']) # インデックスの順序が異なり、一部共通なし
print("--- 価格データ ---")
print(df_price)
print("\n--- 在庫データ ---")
print(df_stock)
# インデックスを基準に結合
joined_df = df_price.join(df_stock)
print("\n--- join() でインデックス結合 (左結合) ---")
print(joined_df)
# 出力例:
# price stock
# Apple 100 120.0
# Banana 150 50.0
# Cherry 200 NaN
join()は、デフォルトで呼び出し元のDataFrame(例: df_price)のインデックスを基準に結合します。
join()とhow引数
join()でもhow引数を使って結合タイプを指定できます。'inner', 'left', 'right', 'outer'が使用可能です。
import pandas as pd
df_A = pd.DataFrame({'ValA': [10, 20]}, index=['X', 'Y'])
df_B = pd.DataFrame({'ValB': [30, 40]}, index=['Y', 'Z'])
print("\n--- df_A ---")
print(df_A)
print("\n--- df_B ---")
print(df_B)
# 外部結合 (outer join)
joined_outer_df = df_A.join(df_B, how='outer')
print("\n--- join() で外部結合 ---")
print(joined_outer_df)
# 出力例:
# ValA ValB
# X 10.0 NaN
# Y 20.0 30.0
# Z NaN 40.0
on引数:列をキーにjoin()を使う場合
join()はインデックスベースが基本ですが、on引数を使って、呼び出し元のDataFrameの列をキーとして結合することもできます。この場合、結合される側のDataFrameはインデックスをキーとして使用します。
import pandas as pd
df_main = pd.DataFrame({
'Product': ['Apple', 'Banana', 'Cherry'],
'CategoryID': [1, 2, 1]
})
df_category = pd.DataFrame({
'CategoryName': ['Fruit', 'Vegetable'],
}, index=[1, 2]) # CategoryIDをインデックスに持つ
# df_mainの'CategoryID'列とdf_categoryのインデックスを結合
joined_on_col = df_main.join(df_category, on='CategoryID')
print("\n--- join() で列とインデックスを結合 ---")
print(joined_on_col)
# 出力例:
# Product CategoryID CategoryName
# 0 Apple 1 Fruit
# 1 Banana 2 Vegetable
# 2 Cherry 1 Fruit
merge() vs join():使い分けのヒント 💡
| 機能 | merge() |
join() |
| 主な用途 | 共通の列をキーにした結合 | 主にインデックスをキーにした結合 |
| 柔軟性 | 列名が異なる場合もleft_on/right_onで対応可能 |
列とインデックスの結合もonで可能 |
| SQL類似性 | SQLのJOINに非常に似ている |
インデックスベースの結合に特化 |
| 推奨場面 | – 複数のDataFrameに共通のID列がある場合<br>- 結合キーとなる列名が異なる場合 |
– DataFrameのインデックスが共通のキーである場合<br>- 複数のDataFrameをインデックス基準で手軽に結合したい場合 |
基本的にはmerge()を使うのが一般的です。 多くの場合はcustomer_idやproduct_idのような特定の列をキーに結合することが多いためです。
join()は、インデックスがすでに意味のある識別子として機能している場合や、複数列のDataFrameをインデックスで手軽に結合したい場合に選択すると良いでしょう。
まとめ
Pandasのmerge()関数とjoin()メソッドは、データ統合において欠かせない強力なツールです。
-
merge(): 主に列をキーに結合。how引数でinner,left,right,outer結合を制御。異なる列名でも結合可能。 -
join(): 主にインデックスをキーに結合。on引数で列とインデックスの結合も可能。
これらの結合機能を適切に使いこなすことで、散在するデータを統合し、より深い洞察を得るための基盤を築くことができます。ぜひ様々なデータセットでこれらの結合操作を試して、あなたのデータ分析スキルを向上させてください!

