pandas.DataFrameを結合するmerge, join(列・インデックス基準)
共通のデータ列を持つ複数のpandas.DataFrame
をその列の値に従って結合するには、pandas.merge()
関数またはpandas.DataFrame
のmerge()
メソッドを使う。
インデックス列を基準にする場合はpandas.DataFrame
のjoin()
メソッドも使える。
pandas.DataFrame
を縦横に連結するにはpandas.concat()
関数を使う。
本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。以下の2つのpandas.DataFrame
を例とする。
import pandas as pd
print(pd.__version__)
# 2.0.3
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
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
この場合、両方の列が残るので、必要ない場合は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'
left
とright
両方のDataFrame
に共通するキーを持つ行が残る。これがデフォルト。
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'
left
を基準に結合。right
にキーが存在しない行も残る。左外部結合とも呼ばれる。
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'
right
を基準に結合。left
にキーが存在しない行も残る。右外部結合とも呼ばれる。
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'
left
とright
のすべての行が残る。完全外部結合とも呼ばれる。
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
交差結合(CROSS JOIN): how='cross'
left
とright
のすべての組み合わせを生成して結合する。デフォルトでは列名に_x
, _y
というサフィックス(接尾辞)が付く。後述の引数suffixes
で指定可能。
print(pd.merge(df_ab, df_ac, how='cross'))
# a_x b a_y c
# 0 a_1 b_1 a_1 c_1
# 1 a_1 b_1 a_2 c_2
# 2 a_1 b_1 a_4 c_4
# 3 a_2 b_2 a_1 c_1
# 4 a_2 b_2 a_2 c_2
# 5 a_2 b_2 a_4 c_4
# 6 a_3 b_3 a_1 c_1
# 7 a_3 b_3 a_2 c_2
# 8 a_3 b_3 a_4 c_4
how='cross'
のときは引数on
やleft_on
, right_on
を指定するとエラーになる。
# print(pd.merge(df_ab, df_ac, on='a', how='cross'))
# MergeError: Can not pass on, right_on, left_on or set right_index=True or left_index=True
データの情報を取得: 引数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用サフィックス]
のように2つの要素のリストやタプルを指定する。
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
複数の列をキーとする場合
これまでの例はキーとする列が一列だけだったが、複数の列をキーとすることもできる。
列を追加した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
共通する列名の列が複数存在していても片方の列のみをキーとすることもできる。重複する列名にはサフィックスがつけられる。上述のように引数suffixes
で任意のサフィックスを指定可能。
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_1 NaN x_1 c_1
# 1 a_2 b_2 x_2 c_2
# 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
print(pd.merge(df_abx, df_acx, how='cross'))
# a_x b x_x a_y c x_y
# 0 a_1 b_1 x_2 a_1 c_1 x_1
# 1 a_1 b_1 x_2 a_2 c_2 x_2
# 2 a_1 b_1 x_2 a_4 c_4 x_2
# 3 a_2 b_2 x_2 a_1 c_1 x_1
# 4 a_2 b_2 x_2 a_2 c_2 x_2
# 5 a_2 b_2 x_2 a_4 c_4 x_2
# 6 a_3 b_3 x_3 a_1 c_1 x_1
# 7 a_3 b_3 x_3 a_2 c_2 x_2
# 8 a_3 b_3 x_3 a_4 c_4 x_2
インデックスをキーに指定: 引数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()
メソッドを使うこともできる。
pd.DataFrame.join()の基本的な使い方
インデックスをキーとして結合するには、pandas.DataFrame
のjoin()
メソッドを使うこともできる。pandas.join()
関数は提供されていない。使い方は概ねmerge()
と同じ。
インデックスを設定したpandas.DataFrame
を例とする。
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
引数how
join()
はインデックスをキーとして結合する。
merge()
と異なり、左結合(how='left'
)がデフォルト。呼び出し元のpandas.DataFrame
がleft
、引数に指定するpandas.DataFrame
がright
に対応する。
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
print(df_ab_i.join(df_ac_i, how='left'))
# 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='right'))
# b c
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
# a_4 NaN c_4
print(df_ab_i.join(df_ac_i, how='outer'))
# b c
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
# a_3 b_3 NaN
# a_4 NaN c_4
print(df_ab_i.join(df_ac_i, how='cross'))
# b c
# 0 b_1 c_1
# 1 b_1 c_2
# 2 b_1 c_4
# 3 b_2 c_1
# 4 b_2 c_2
# 5 b_2 c_4
# 6 b_3 c_1
# 7 b_3 c_2
# 8 b_3 c_4
引数on
呼び出し元の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
引数lsuffix, rsuffix
結果に重複する列名がある場合、デフォルトではエラーとなる。引数lsuffix
とrsuffix
を指定する必要がある。
df_ab_i2 = df_ac_i.rename(columns={'c': 'b'})
print(df_ab_i2)
# b
# a
# a_1 c_1
# a_2 c_2
# a_4 c_4
# print(df_ab_i.join(df_ab_i2))
# ValueError: columns overlap but no suffix specified: Index(['b'], dtype='object')
print(df_ab_i.join(df_ab_i2, lsuffix='_left', rsuffix='_right'))
# b_left b_right
# a
# a_1 b_1 c_1
# a_2 b_2 c_2
# a_3 b_3 NaN
複数のpandas.DataFrameをリストで指定
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