Pandas DataFrameの結合を極める!merge, joinでデータ統合 🤝


 

データ分析では、複数のデータソースから得られた情報を組み合わせて分析することが不可欠です。PandasのDataFrameも例外ではなく、異なるDataFrameを結合する機能はデータ統合の要となります。この結合操作の主役となるのが、merge()関数と**join()メソッド**です。これらの機能を使うことで、リレーショナルデータベースのように、共通のキー(列やインデックス)に基づいてDataFrameを横方向に連結できます。

この記事では、merge()join()のそれぞれの特徴、基本的な使い方、そして様々な結合タイプ(内部結合、左結合、右結合、外部結合)について、具体的なコード例を交えながら詳しく解説します。


 

merge():SQLライクな結合の決定版 ✨

 

pd.merge()関数は、SQLのJOIN操作に最も似ており、一つ以上の共通の列(キー)に基づいてDataFrameを結合する際に非常に強力です。

 

基本的な結合(内部結合:how='inner'

 

merge()のデフォルトの結合タイプは**内部結合(inner)**です。これは、両方のDataFrameに共通して存在するキーのみを結合します。

Python
 
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が入ります。

Python
 
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_onright_onを使ってそれぞれ指定します。

Python
 
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():インデックス基準の結合に特化 🔗

 

DataFramejoin()メソッドは、インデックス(行ラベル)に基づいてDataFrameを結合する際に特に便利です。merge()でもインデックス結合は可能ですが、join()の方がより簡潔に記述できます。

 

基本的な結合(インデックス同士の結合)

 

join()のデフォルトは左結合(how='left')です。

Python
 
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'が使用可能です。

Python
 
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インデックスをキーとして使用します。

Python
 
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引数で列とインデックスの結合も可能。

これらの結合機能を適切に使いこなすことで、散在するデータを統合し、より深い洞察を得るための基盤を築くことができます。ぜひ様々なデータセットでこれらの結合操作を試して、あなたのデータ分析スキルを向上させてください!