pandasのmergeによる表結合を深掘り解説(チートシート形式)
pandasを使ってデータを操作する場合、mergeやjoinを使った表の結合が行われます。機械学習やデータ分析では高い頻度で行う操作ですが、記述の方法を忘れやすいのでチートシート形式で整理しました。本記事では、pandasの操作のうち、mergeによる表結合に特化して解説します。
データの準備
この記事では以下の2つのデータフレームを利用します。
import pandas as pd
df0 = pd.DataFrame({'id': [1,2,3], 'age': [18, 20, 33], 'c': ['x', 'y', 'z']})
df1 = pd.DataFrame({'id': [1,2,4], 'Age': [18, 20, 33], 'c': ['x', 'm', 'n']})
print(df0)
# id age c
# 0 1 18 x
# 1 2 20 y
# 2 3 33 z
print(df1)
# id Age c
# 0 1 18 x
# 1 2 20 m
# 2 4 33 n2つのデータフレームの内容は以下になります。
| インデックス | id | age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | y |
| 2 | 3 | 33 | z |
| インデックス | id | Age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | n |
| 2 | 4 | 33 | m |
pandasのmerge()の使い方(基本)
基本(merge)
基本的な書き方です。pd.mergeには結合する2つのデータフレームを指定します
df = pd.merge(df0, df1)
print(df)
# id age c_x Age c_y
# 0 1 18 x 18 x
# 1 2 20 y 20 m2つの表の共通のものがマージされて、c列がc_x, c_yの2つで結合されます。
| インデックス | id | age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | y |
| 2 | 3 | 33 | z |
| インデックス | id | Age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | n |
| 2 | 4 | 33 | m |
on : 結合するキーを指定(列を指定)
キーを指定(on)
onを使うことで、結合するキーを指定することが可能です。

onを省略しても良いですが、明示しておいた方が後々コードが読みやすいです
df = pd.merge(df0, df1, on='id')
print(df)
# id age c_x Age c_y
# 0 1 18 x 18 x
# 1 2 20 y 20 midで結合していますが、結果は「基本」の例と同じです。
複数のキーを指定(on)
onには複数のキー列を指定することも可能です。複数キーを指定する場合は、列名をリスト形式で渡します。
df = pd.merge(df0, df1, on = ['id', 'c'])
print(df)
# id age c Age
# 0 1 18 x 18例では、idとc列をキーとして結合しています。idとc列が同一なものは1つですので、結果は1行になります。
| インデックス | id | age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | y |
| 2 | 3 | 33 | z |
| インデックス | id | Age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | n |
| 2 | 4 | 33 | m |
キーを指定(left_on, right_on)
2つの表の列名が異なっていても、left_on, right_onを指定することでキーとして結合することが可能です。
df = pd.merge(df0, df1, left_on = 'age', right_on = 'Age')
print(df)
# id_x age c_x id_y Age c_y
# 0 1 18 x 1 18 x
# 1 2 20 y 2 20 m
# 2 3 33 z 4 33 n例では、df0のageとdf1のAgeの列をキーとして結合を行なっています。キーとして指定しなかった各列は_x, _yとして列が追加されます。
| インデックス | id | age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | y |
| 2 | 3 | 33 | z |
| インデックス | id | Age | c |
| 0 | 1 | 18 | x |
| 1 | 2 | 20 | n |
| 2 | 4 | 33 | m |
ageとAgeは重複している情報なので、dropを使って片方を削除することが可能です。

列削除なので、drop(..., axis=1)とaxisをつける必要があります
df = pd.merge(df0, df1, left_on = 'age', right_on = 'Age').drop('Age', axis=1)
print(df)
# id_x age c_x id_y c_y
# 0 1 18 x 1 x
# 1 2 20 y 2 m
# 2 3 33 z 4 nhow : 結合方法を指定
howを使って結合方法も指定することができます。デフォルトはinnerなので指定しないとinner結合されます。
inner
両方に共通する行が残ります
df = pd.merge(df0, df1, on='id', how = 'inner')
print(df)
# id age c_x Age c_y
# 0 1 18 x 18 x
# 1 2 20 y 20 mouter
両方の列が全て残ります。値がない部分にはNaNが挿入されます。
df = pd.merge(df0, df1, on='id', how = 'outer')
print(df)
# id age c_x Age c_y
# 0 1 18.0 x 18.0 x
# 1 2 20.0 y 20.0 m
# 2 3 33.0 z NaN NaN
# 3 4 NaN NaN 33.0 nleft(左結合)
左(mergeの先に書いたデータフレーム)を基準として結合します。右のデータフレームに存在しない行は、値をNaNにします。

ちなみに、私は、leftによる結合を結構行います
df = pd.merge(df0, df1, on='id', how = 'left')
print(df)
# id age c_x Age c_y
# 0 1 18 x 18.0 x
# 1 2 20 y 20.0 m
# 2 3 33 z NaN NaNright(右結合)
右を基準にして結合します。leftと似たような動きです。
df = pd.merge(df0, df1, on='id', how = 'right')
print(df)
# id age c_x Age c_y
# 0 1 18.0 x 18 x
# 1 2 20.0 y 20 m
# 2 4 NaN NaN 33 ncross(交差結合)
全ての組み合わせを生成して結合します。

個人的には、あまり使う機会がありません

データが大きくなると組み合わせ爆発でメモリがなくなりますから使う機会は少ないです
df = pd.merge(df0, df1, how = 'cross')
print(df)
# id_x age c_x id_y Age c_y
# 0 1 18 x 1 18 x
# 1 1 18 x 2 20 m
# 2 1 18 x 4 33 n
# 3 2 20 y 1 18 x
# 4 2 20 y 2 20 m
# 5 2 20 y 4 33 n
# 6 3 33 z 1 18 x
# 7 3 33 z 2 20 m
# 8 3 33 z 4 33 nindicator : 結合情報を追加
indicatorを設定することで、both, left_only, right_onlyの分類を追加することができます。
df = pd.merge(df0, df1, on='id', how = 'outer', indicator = True)
print(df)
# id age c_x Age c_y _merge
# 0 1 18.0 x 18.0 x both
# 1 2 20.0 y 20.0 m both
# 2 3 33.0 z NaN NaN left_only
# 3 4 NaN NaN 33.0 n right_onlyまとめ
結合にはjoinもありますが、似たような使い方です。個人的には、mergeの方が使いやすいのでここではmergeを説明しました。
