PandasでDataFrameを結合する

2021年01月03日

SQLで言うところの JOIN をPandasでプログラムにて実行する方法を紹介します。複数のデータソースからデータを持ってくるときに役立ちます。

pandas.merge を使う

結合は Pandas の merge() APIで行います。

import pandas as pd

pd.merge(
    dataframe1,   # 結合されるテーブル(左)
    dataframe2,   # 結合するテーブル (右)
    how='inner',  # inner: 内部結合, left: 左結合, right: 右結合
    on='id',      # 結合キー
)

2つのDataFrameと結合キーを指定して、テーブルJoinを実行します。

サンプルプログラム

以下のサンプルデータを内部結合してみます。

■ sazae.csv ユーザIDと登録日が記録されたcsv

id,name,registered_date
1,サザエさん,2020-12-01
2,波平さん,2020-12-02
3,マスオさん,2020-12-03

■ sazae_gender.csv ユーザIDと性別が記録されたcsv

user_id,gender
1,女
2,男
3,男

● 内部結合

In [19]: user_df = pd.read_csv('sazae.csv')

In [20]: gender_df = pd.read_csv('sazae_gender.csv')

In [21]: pd.merge(
    ...:     user_df,
    ...:     gender_df,
    ...:     how='inner',
    ...:     left_on='id',
    ...:     right_on='user_id',
    ...: )
Out[21]: 
   id   name registered_date  user_id gender
0   1  サザエさん      2020-12-01        11   2   波平さん      2020-12-02        22   3  マスオさん      2020-12-03        3

sazae.csv では結合キーの列名が id 。 sazae_gender.csv では結合キーの列名が user_id で列名が一致しませんが、merge() API ではこのケースにも対応できるように、 left_on , right_on パラメータでそれぞれのキー列名を指定することができます。

left_onに指定するキー名は第一引数に渡したDataFrameと対応関係があり、right_onに指定するキー名は第二引数に渡したDataFrameと対応関係があります。

● 左結合・右結合

how に left , right を指定すると左結合、右結合になります。1対多のデータを結合する際によく利用します。上記のデータ例だと少々分かりにくいので、sazae_gender.csv にuser_id 4番の性別データを追加しておきます。ユーザデータのsazae.csvはそのままにしておきます。SQLに明るい方であれば、左結合と右結合の実行結果は予想付くかと思います。

In [29]: gender_df = gender_df.append({ 'user_id': 4, 'gender': '女' }, ignore_index=True)

In [30]: gender_df
Out[30]: 
   user_id gender
0        11        22        33        4

左結合

左テーブルが軸となるため、左結合をしてもinner joinと同じ結果になります。user_id 4番の性別データは結合先のユーザがいないので無視されますね!

In [31]: pd.merge(
    ...:     user_df,
    ...:     gender_df,
    ...:     how='left',
    ...:     left_on='id',
    ...:     right_on='user_id',
    ...: )
Out[31]: 
   id   name registered_date  user_id gender
0   1  サザエさん      2020-12-01        11   2   波平さん      2020-12-02        22   3  マスオさん      2020-12-03        3

右結合

右結合をすると右テーブルが軸となるため、user_id 4番の名前と登録日の列が欠落データの NaN となります。

In [32]: pd.merge(
    ...:     user_df,
    ...:     gender_df,
    ...:     how='right',
    ...:     left_on='id',
    ...:     right_on='user_id',
    ...: )
Out[32]: 
    id   name registered_date  user_id gender
0  1.0  サザエさん      2020-12-01        11  2.0   波平さん      2020-12-02        22  3.0  マスオさん      2020-12-03        33  NaN    NaN             NaN        4

所感

ほぼSQLの考え方と同様に簡単にプログラマブルにテーブル結合ができます。Webサービスを運用しているとデータソースとしてRDBやGoogle BigQueryなど複数に跨ることが多いはずですので、数字分析をする際にPandasを利用するのであれば結合処理の嵐に見舞われるのではないかと思います。

プログラムでfor文書いて集計バッチを力技で書くことを考えると、かなり簡素なプログラムで実現が出来てしまいます。Pandasは標準で様々なデータソースとの入出力インタフェースを備えているので、データをクロスで集計するのにとても便利です。


Web系エンジニアでPython好き。バックエンド/フロントエンド問わずマルチな方面でエンジニアリングしています。