インデックスによる結合
DataFrame.join()を使い、merge()でleft_index/right_index=Trueを設定して、インデックスを揃えてDataFrameを結合します。
「インデックスによる結合」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。
インデックスベースの Join
これまでは、通常の列の値を照合して DataFrame を merge してきました。しかし、照合したい情報が列ではなく DataFrame のインデックスに保存されている場合もあります。Pandas では、DataFrame.join() や、left_index=True または right_index=True パラメータを指定した pd.merge() によって、インデックスベースの join を実行できます。
DataFrame.join() メソッド
DataFrame.join(other) は、デフォルトで両方の DataFrame のインデックスを使って結合する便利なメソッドです。これは、left_index=True, right_index=True を指定した pd.merge() の呼び出しと同じです。デフォルトの join の種類は 'left' で、デフォルトが 'inner' の pd.merge() とは異なります。正しい結果を得るには、両方の DataFrame に意味のあるインデックスラベルが設定されている必要があります。
import pandas as pd
profiles = pd.DataFrame(
{'age': [25, 30, 22]},
index=['alice', 'bob', 'carol']
)
scores = pd.DataFrame(
{'score': [88, 95, 70]},
index=['alice', 'carol', 'dave']
)
# join: left join on index (default)
result = profiles.join(scores)
print(result)
# age score
# alice 25 88.0
# bob 30 NaN <- bob has no score
# carol 22 95.0join() で Join の種類を制御する
pd.merge()の場合と同様に、howパラメータをjoin()に渡すことで、どの行を保持するかを制御できます。指定できる値は'left'(デフォルト)、'right'、'inner'、'outer'です。たとえばhow='inner'を指定すると、両方のDataFrameに存在するインデックスだけが保持されます。そのため、右側のテーブルに一致するインデックスがなければ、aliceの行は削除されます。
# Inner join on index: only rows present in BOTH indices
print(profiles.join(scores, how='inner'))
# age score
# alice 25 88
# carol 22 70
# Outer join: all indices from both
print(profiles.join(scores, how='outer'))
# age score
# alice 25.0 88.0
# bob 30.0 NaN
# carol 22.0 70.0
# dave NaN 95.0複数のDataFrameを一度に結合する
join()がpd.merge()より優れている大きな点は、DataFrameのリストを受け取り、1回の呼び出しでそれらすべてを呼び出し元のDataFrameに結合できることです。すべてのDataFrameでインデックスが揃っている必要があります。これは、ユーザーIDや日付など、同じキーでインデックス付けされた特徴量テーブルが多数あり、それらを1つの横長のDataFrameにまとめたい場合に非常に便利です。
emails = pd.DataFrame({'email': ['a@x.com', 'b@x.com', 'c@x.com']},
index=['alice', 'bob', 'carol'])
city = pd.DataFrame({'city': ['NY', 'LA', 'SF']},
index=['alice', 'bob', 'carol'])
# Join multiple DataFrames at once
result = profiles.join([emails, city])
print(result)
# age email city
# alice 25 a@x.com NY
# bob 30 b@x.com LA
# carol 22 c@x.com SF一方のテーブルの列と、もう一方のテーブルのインデックスで結合する
pd.merge()では、left_on/right_indexまたはleft_index/right_onを使って、列ベースの照合とインデックスベースの照合を組み合わせられます。これは、一方のDataFrameではキーを列に格納し、もう一方ではキーをインデックスとして使用している場合に便利です。join()だけでは、この処理は実現できません。
# orders has customer_id as a column; customers is indexed by customer_id
customers_indexed = pd.DataFrame(
{'name': ['Alice', 'Bob', 'Carol']},
index=[101, 102, 103]
)
orders = pd.DataFrame({
'order_id': [1, 2, 3],
'customer_id': [101, 102, 101]
})
result = pd.merge(orders, customers_indexed,
left_on='customer_id', right_index=True)
print(result)
# order_id customer_id name
# 0 1 101 Alice
# 2 3 101 Alice
# 1 2 102 Bobmerge()でleft_indexとright_indexを使う
両方のDataFrameでキーがインデックスになっている場合は、pd.merge(left, right, left_index=True, right_index=True)を使用します。これはjoin()と同等ですが、デフォルトの結合方法が'inner'で、パラメータがより明示的です。さらに、suffixesやindicatorなど、その他すべてのpd.merge()パラメータも利用できます。
# Both DataFrames indexed by user_id
demog = pd.DataFrame({'age': [25, 30]}, index=[1, 2])
behav = pd.DataFrame({'clicks': [10, 5]}, index=[1, 2])
# Equivalent joins
result1 = demog.join(behav) # left join
result2 = pd.merge(demog, behav, left_index=True, right_index=True) # inner join
print(result1)
print(result2)インデックスベースの結合を使う理由
インデックスベースの結合は、DataFrameがユーザーID、商品SKU、日付などの意味のある識別子を自然なキーとして持っている場合に適しています。結合にインデックスを使うと、重複したキー列でDataFrameが煩雑になるのを避けられます。また、Pandasはインデックスをソート済みの構造で管理するため、O(log n)の検索が可能になり、処理が速くなる場合があります。特に、DatetimeIndexが自然な結合キーとなる時系列データでよく使われます。
# Time series example: join temperature and humidity by date index
import numpy as np
dates = pd.date_range('2024-01-01', periods=5)
temp = pd.DataFrame({'temp_c': [10, 12, 9, 11, 13]}, index=dates)
humid = pd.DataFrame({'humidity': [65, 70, 60, 75, 68]}, index=dates)
weather = temp.join(humid)
print(weather.head())重複する列名への対処
両方のDataFrameに、キー以外で同じ名前の列がある場合、lsuffixとrsuffixパラメータを指定しない限り、join()はデフォルトでValueErrorを発生させます。これらのパラメータはpd.merge()のsuffixesと同様に機能し、左側と右側のDataFrameにある重複列名に、それぞれ文字列を追加します。
df_a = pd.DataFrame({'value': [1, 2]}, index=['x', 'y'])
df_b = pd.DataFrame({'value': [10, 20]}, index=['x', 'y'])
# Without suffixes: raises ValueError
# result = df_a.join(df_b)
# With suffixes: disambiguate column names
result = df_a.join(df_b, lsuffix='_left', rsuffix='_right')
print(result)
# value_left value_right
# x 1 10
# y 2 20結合前にset_indexを使う
よくある処理の流れは、列をインデックスに設定することです。これにより、join()の構文を使って結合できます。結合後にreset_index()を使うと、キーを通常の列に戻せます。このパターンでは、キーをインデックスに設定し、結合し、その後キーを列に戻すという流れが自然に読み取れるため、後からコードを読む人にも意図が伝わりやすくなります。
orders_col = pd.DataFrame({'order_id': [1,2,3], 'customer_id': [10,20,10], 'amount': [100,200,150]})
cust_col = pd.DataFrame({'customer_id': [10,20], 'name': ['Alice','Bob']})
result = (
orders_col.set_index('customer_id')
.join(cust_col.set_index('customer_id'), how='left')
.reset_index()
)
print(result)SeriesをDataFrameのインデックスに揃える
Seriesにもインデックスがあり、代入によってDataFrameに新しい列として追加できます。このときPandasは、Seriesの値を一致するインデックスラベルに自動的に揃えます。これは、merge()やjoin()を呼び出さずにSeriesから1列だけ追加したい場合に使える、軽量なインデックスベースの結合です。
df = pd.DataFrame({'sales': [100, 200, 150]}, index=['A', 'B', 'C'])
tax_rate = pd.Series({'A': 0.1, 'B': 0.2, 'C': 0.15})
# Index alignment: Series aligns to DataFrame index automatically
df['tax'] = df['sales'] * tax_rate
print(df)
# sales tax
# A 100 10.0
# B 200 40.0
# C 150 22.5インデックス結合のパフォーマンス
ソート済みのインデックスで結合すると、通常の列で結合するより高速です。これは、Pandasがソート済みのインデックスに対して二分探索を使うためです。同じキーで繰り返し結合する場合は、パイプラインの最初に一度だけ、そのキーをインデックスに設定しましょう。多くのファイルに対してDatetimeIndexで何千回も結合する時系列処理では、特に重要です。
# Sort index before repeated joins for speed
left = left.sort_index()
right = right.sort_index()
# Both sorted -> Pandas uses merge path with binary search
result = left.join(right, how='inner')
# Check if index is sorted
print('Left sorted:', left.index.is_monotonic_increasing)
print('Right sorted:', right.index.is_monotonic_increasing)理解度チェック
このレッスンで学んだインデックスベースの結合について、理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、DataFrame.join()はデフォルトでインデックスを使い、左結合を行うこと、left_index=True/right_index=Trueを指定したpd.merge()を使うと、より細かく制御できること、join()にリストを渡すと複数のDataFrameを一度に結合できること、そしてソート済みのインデックスによって結合のパフォーマンスが向上することを学びました。次は、pivot_tableを使ったDataFrameの形状変更について学びます。
よくある質問
「インデックスによる結合」レッスンは無料ですか?
はい。「インデックスによる結合」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。
「インデックスによる結合」で何を学びますか?
DataFrame.join()を使い、merge()でleft_index/right_index=Trueを設定して、インデックスを揃えてDataFrameを結合します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Pandas & NumPy Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「インデックスによる結合」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPandas & NumPy Academyレッスンでコードを書いて実行できますか?
はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。