pandas.DataFrameを結合するmerge, join(列・インデックス基準)
日付や名前などの共通のデータ列を持っている複数のpandas.DataFrame
をその列の値に従って結合するにはpandas.merge()
関数またはpandas.DataFrame
のmerge()
メソッドを使う。
インデックス列を基準にする場合はpandas.merge()
関数も使えるし、pandas.DataFrame
のjoin()
メソッドも使える。
ここでは以下の内容について説明する。
pd.merge()
,pd.DataFrame.merge()
の基本的な使い方- キーとする列を指定: 引数
on
,left_on
,right_on
- 結合方法を指定: 引数
how
- 内部結合(inner_join):
how='inner'
- 左結合(left_join):
how='left'
- 右結合(right_join):
how='right'
- 外部結合(outer_join):
how='outer'
- 内部結合(inner_join):
- データの情報を取得: 引数
indicator
- 列名が重複している場合のサフィックスを指定: 引数
suffixes
- 複数の列をキーとする場合
- キー列でソート: 引数
sort
- インデックスをキーに指定: 引数
left_index
,right_index
pd.DataFrame.join()
の基本的な使い方
以下の2つのpandas.DataFrame
を例とする。
import pandas as pd
df_ab = pd.DataFrame({'a': ['a_1', 'a_2', 'a_3'], 'b': ['b_1', 'b_2', 'b_3']})
df_ac = pd.DataFrame({'a': ['a_1', 'a_2', 'a_4'], 'c': ['c_1', 'c_2', 'c_4']})
print(df_ab)
# a b
# 0 a_1 b_1
# 1 a_2 b_2
# 2 a_3 b_3
print(df_ac)
# a c
# 0 a_1 c_1
# 1 a_2 c_2
# 2 a_4 c_4
なお、pandas.DataFrame
を縦横に連結するにはpandas.concat()
関数を使う。以下の記事を参照。
pd.merge(), pd.DataFrame.merge()の基本的な使い方
pd.merge()
関数では第一引数left
と第二引数right
に結合する2つのpandas.DataFrame
を指定する。
print(pd.merge(df_ab, df_ac))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
merge()
メソッドの場合はleft
に相当するpandas.DataFrame
からメソッドを呼び出し、right
に相当するpandas.DataFrame
を引数に指定する。
print(df_ab.merge(df_ac))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
どちらも結合されたpandas.DataFrame
を返す。
以降で説明する引数はpd.merge()
関数でもmerge()
メソッドでも共通。
キーとする列を指定: 引数on, left_on, right_on
デフォルトでは2つのpandas.DataFrame
に共通する列名の列をキーとして結合処理が行われる。
明示的に指定する場合は引数on
を使う。省略して問題ない場合も明示しておいたほうが分かりやすい。
print(pd.merge(df_ab, df_ac, on='a'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
引数left_on
, right_on
でそれぞれのpandas.DataFrame
の列名を別々に指定することも可能。
df_ac_ = df_ac.rename(columns={'a': 'a_'})
print(df_ac_)
# a_ c
# 0 a_1 c_1
# 1 a_2 c_2
# 2 a_4 c_4
print(pd.merge(df_ab, df_ac_, left_on='a', right_on='a_'))
# a b a_ c
# 0 a_1 b_1 a_1 c_1
# 1 a_2 b_2 a_2 c_2
この場合、2つの列が残るので、必要ない場合はdrop()
メソッドで削除する。
print(pd.merge(df_ab, df_ac_, left_on='a', right_on='a_').drop(columns='a_'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
on
, left_on
, right_on
に列名のリストを指定して複数の列をキーとすることもできる。後述。
結合方法を指定: 引数how
結合方法は引数how
に文字列で指定する。デフォルトはhow='inner'
。
データがない要素は欠損値NaN
となる。欠損値NaN
の処理については以下の記事を参照。
内部結合(inner_join): how='inner'
print(pd.merge(df_ab, df_ac, on='a', how='inner'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
左結合(left_join): how='left'
print(pd.merge(df_ab, df_ac, on='a', how='left'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
# 2 a_3 b_3 NaN
右結合(right_join): how='right'
print(pd.merge(df_ab, df_ac, on='a', how='right'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
# 2 a_4 NaN c_4
外部結合(outer_join): how='outer'
print(pd.merge(df_ab, df_ac, on='a', how='outer'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
# 2 a_3 b_3 NaN
# 3 a_4 NaN c_4
データの情報を取得: 引数indicator
引数indicator
をTrue
とすると、元データの情報を含む列が追加される。
デフォルトでは_merge
という列が追加され、both
, left_only
, right_only
のいずれかに分類される。
print(pd.merge(df_ab, df_ac, on='a', how='inner', indicator=True))
# a b c _merge
# 0 a_1 b_1 c_1 both
# 1 a_2 b_2 c_2 both
print(pd.merge(df_ab, df_ac, on='a', how='outer', indicator=True))
# a b c _merge
# 0 a_1 b_1 c_1 both
# 1 a_2 b_2 c_2 both
# 2 a_3 b_3 NaN left_only
# 3 a_4 NaN c_4 right_only
_merge
ではない任意の列名にしたい場合は引数indicator
に文字列を指定する。
print(pd.merge(df_ab, df_ac, on='a', how='outer', indicator='indicator'))
# a b c indicator
# 0 a_1 b_1 c_1 both
# 1 a_2 b_2 c_2 both
# 2 a_3 b_3 NaN left_only
# 3 a_4 NaN c_4 right_only
列名が重複している場合のサフィックスを指定: 引数suffixes
left
とright
でキーにする列以外の列名が重複している場合、デフォルトでは_x
, _y
というサフィックス(接尾辞)がつけられる。
df_ac_b = df_ac.rename(columns={'c': 'b'})
print(df_ac_b)
# a b
# 0 a_1 c_1
# 1 a_2 c_2
# 2 a_4 c_4
print(pd.merge(df_ab, df_ac_b, on='a'))
# a b_x b_y
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
任意のサフィックスをつけたい場合は、引数suffixes
に[left用サフィックス, right用サフィックス]
というリストやタプルを指定する。
print(pd.merge(df_ab, df_ac_b, on='a', suffixes=['_left', '_right']))
# a b_left b_right
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
複数の列をキーとする場合
これまでの例はキーとする列が一列だけだった。複数の列をキーとしたい場合について説明する。
以下の2つのpandas.DataFrame
を例とする。
df_abx = df_ab.assign(x=['x_2', 'x_2', 'x_3'])
df_acx = df_ac.assign(x=['x_1', 'x_2', 'x_2'])
print(df_abx)
# a b x
# 0 a_1 b_1 x_2
# 1 a_2 b_2 x_2
# 2 a_3 b_3 x_3
print(df_acx)
# a c x
# 0 a_1 c_1 x_1
# 1 a_2 c_2 x_2
# 2 a_4 c_4 x_2
共通する列名の列が複数存在する場合、デフォルトですべての列がキーとして処理される。明示的に指定する場合は引数on
に列名のリストを指定する。
print(pd.merge(df_abx, df_acx))
# a b x c
# 0 a_2 b_2 x_2 c_2
print(pd.merge(df_abx, df_acx, on=['a', 'x']))
# a b x c
# 0 a_2 b_2 x_2 c_2
共通する列名の列が複数存在していても片方の列のみをキーとすることも可能。上の例のようにサフィックスがつけられる。
print(pd.merge(df_abx, df_acx, on='a'))
# a b x_x c x_y
# 0 a_1 b_1 x_2 c_1 x_1
# 1 a_2 b_2 x_2 c_2 x_2
異なる列名の列を共通のキーとしたい場合は引数left_on
, right_on
にそれぞれ列名のリストを指定する。
df_acx_ = df_acx.rename(columns={'x': 'x_'})
print(df_acx_)
# a c x_
# 0 a_1 c_1 x_1
# 1 a_2 c_2 x_2
# 2 a_4 c_4 x_2
print(pd.merge(df_abx, df_acx_, left_on=['a', 'x'], right_on=['a', 'x_']))
# a b x c x_
# 0 a_2 b_2 x_2 c_2 x_2
引数how
は単独の列をキーとするときと同様。
print(pd.merge(df_abx, df_acx, on=['a', 'x'], how='inner'))
# a b x c
# 0 a_2 b_2 x_2 c_2
print(pd.merge(df_abx, df_acx, on=['a', 'x'], how='left'))
# a b x c
# 0 a_1 b_1 x_2 NaN
# 1 a_2 b_2 x_2 c_2
# 2 a_3 b_3 x_3 NaN
print(pd.merge(df_abx, df_acx, on=['a', 'x'], how='right'))
# a b x c
# 0 a_2 b_2 x_2 c_2
# 1 a_1 NaN x_1 c_1
# 2 a_4 NaN x_2 c_4
print(pd.merge(df_abx, df_acx, on=['a', 'x'], how='outer'))
# a b x c
# 0 a_1 b_1 x_2 NaN
# 1 a_2 b_2 x_2 c_2
# 2 a_3 b_3 x_3 NaN
# 3 a_1 NaN x_1 c_1
# 4 a_4 NaN x_2 c_4
キー列でソート: 引数sort
キー列でソートする場合は引数sort
をTrue
とする。
print(pd.merge(df_abx, df_acx, on=['a', 'x'], how='outer', sort=True))
# a b x c
# 0 a_1 NaN x_1 c_1
# 1 a_1 b_1 x_2 NaN
# 2 a_2 b_2 x_2 c_2
# 3 a_3 b_3 x_3 NaN
# 4 a_4 NaN x_2 c_4
インデックスをキーに指定: 引数left_index, right_index
インデックス(行ラベル)をキーに指定する場合は、引数left_index
, right_index
をTrue
とする。
引数left_on
, right_on
と組み合わせることが可能。
df_ac_i = df_ac.set_index('a')
print(df_ac_i)
# c
# a
# a_1 c_1
# a_2 c_2
# a_4 c_4
print(pd.merge(df_ab, df_ac_i, left_on='a', right_index=True))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
引数left_index
, right_index
を両方ともTrue
とすることももちろん可能。
df_ab_i = df_ab.set_index('a')
print(df_ab_i)
# b
# a
# a_1 b_1
# a_2 b_2
# a_3 b_3
print(pd.merge(df_ab_i, df_ac_i, left_index=True, right_index=True))
# b c
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
インデックスをキーにする場合は次に示すjoin()
メソッドを使ってもOK。
pd.DataFrame.join()の基本的な使い方
インデックスをキーにする場合はpandas.DataFrame
のjoin()
メソッドを使って結合することもできる。
join()
はmerge()
のようにpandas.join()
関数は用意されておらず、pandas.DataFrame
のメソッドだけなので注意。
merge()
と異なり左結合(how='left'
)がデフォルト。
print(df_ab_i)
# b
# a
# a_1 b_1
# a_2 b_2
# a_3 b_3
print(df_ac_i)
# c
# a
# a_1 c_1
# a_2 c_2
# a_4 c_4
print(df_ab_i.join(df_ac_i))
# b c
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
# a_3 b_3 NaN
print(df_ab_i.join(df_ac_i, how='inner'))
# b c
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
呼び出し元のpandas.DataFrame
のキーとする列を引数on
で指定できる。引数に指定する側のpandas.DataFrame
は常にインデックスがキーとなる。
print(df_ab)
# a b
# 0 a_1 b_1
# 1 a_2 b_2
# 2 a_3 b_3
print(df_ab.join(df_ac_i, on='a'))
# a b c
# 0 a_1 b_1 c_1
# 1 a_2 b_2 c_2
# 2 a_3 b_3 NaN
join()
の引数on
はどちらのpandas.DataFrame
に対する指定なのかややこしいので、インデックスをキーとしない場合はmerge()
を使ったほうが分かりやすいかもしれない。
join()
の第一引数にはpandas.DataFrame
のリストを指定することも可能。
df_ad_i = pd.DataFrame({'a': ['a_1', 'a_4', 'a_5'], 'd': ['d_1', 'd_4', 'd_5']}).set_index('a')
print(df_ad_i)
# d
# a
# a_1 d_1
# a_4 d_4
# a_5 d_5
print(df_ab_i.join([df_ac_i, df_ad_i]))
# b c d
# a
# a_1 b_1 c_1 d_1
# a_2 b_2 c_2 NaN
# a_3 b_3 NaN NaN
print(df_ac_i.join([df_ad_i, df_ab_i]))
# c d b
# a
# a_1 c_1 d_1 b_1
# a_2 c_2 NaN b_2
# a_4 c_4 d_4 NaN