【Python】再帰関数とPandasのmergeを使って 3つ以上のDataFrameを結合する方法

この記事では、再帰関数とPandasのを用いることで、複数のDataFrameに対して特定列のみを取り出す方法を紹介しています。

3つ以上のDataFrameを再帰関数とmergeを使って結合するイメージ図

▲図に表すとこんな感じです。

上図では結合したいDataFrameが3つしかありませんが、いくつもある場合を想定しています。

結合したい各DataFrame(df1,df2,df3,…)は、

  • sample_202106.csv
  • sample_202107.csv
  • sample_202108.csv

のCSVファイルから作るものとします。

例えば、sample_202106.csvの中身は以下のようになります。

会社,件数
A社,20
B社,30
C社,20

‘会社’列は固定して、各データフレームから’件数‘列のみを取り出して結合します。

その際、件数のカラム名を、ファイル名の年月の部分’202106‘に変更します。

各dfの’件数’列には、A社~E社のデータが全てあるとは限りません。

‘会社’列を固定する場合、Pandasのmergeのパラメータ「on」を使えば良いので、mergeを使って書いてみます。

まずdf1df2だけをmergeで結合する場合について考えてみます。

pd.merge(df1, df2, on='会社',how='outer')

で結合できます。

ただし、df1,df2は、

df1 = pd.read_csv('sample_202106.csv')
df1 = df1.columns = ['会社', 202106]
df2 = pd.read_csv('sample_202107.csv')
df2 = df2.columns = ['会社', 202107]

です。

3つ以上のDataFrameを再帰関数とmergeを使って結合するイメージ図

pd.merge(df1, df2, on=’会社’,how=’outer’)の出力結果

続いて、(df1とdf2を結合したデータフレーム)とdf3をmergeで結合する場合について考えてみます。すると、

pd.merge(df12, df3, on='会社',how='outer')

と表現できます。ただし、

df12=pd.merge(df1, df2, on='会社',how='outer')

です。

3つ以上のDataFrameを再帰関数とmergeを使って結合するイメージ図

pd.merge(df12, df3, on=’会社’,how=’outer’)の出力結果

これを続けていけば、任意の数のdfをmergeによってすべて結合することができそうです。

df12を代入した場合、

pd.merge(pd.merge(df1, df2, on='会社',how='outer'), df3, on='会社',how='outer')

となります。一応このデータフレームに対して、さらにdf4をmergeすることを考えてみます。すると、

pd.merge(pd.merge(pd.merge(df1, df2, on='会社',how='outer'), df3, on='会社',how='outer'), df4, on='会社',how='outer')

となります。n個のデータフレームを結合したい場合について考えてみると、この形なら再帰関数を使えば実現できそうです。

その前に、ここでdf1,df2,…を作成するための関数 make_df を定義します。

def make_df(ym_list):
    df = pd.read_csv('sample_' + ym_list + '.csv')
    df.columns = ['会社', ym_list]
    return df
  • make_df(‘202106’)とすると、df1
  • make_df(‘202107’)とすると、df2
  • make_df(‘202108’)とすると、df3

が返ってくるような関数です。

さて、make_dfを定義したところで、n個のデータフレームを結合する関数 merge_df(n)について考えてみます。

まずはn=3で考えてみます。つまり、df1・df2・df3の3つを結合する場合について考えます。

ym_list=['202106', '202107', '202108']

とすると、merge_df(3)は以下のように考えることができます。merge_df(2)を使えることを意識すると、

(merge_df(2))と(df3)をmergeしたデータフレーム

と表現できます。つまり、

(df1とdf2をmergeしたデータフレーム)と(make_df(ym_list[2])をmergeしたデータフレーム

です。コードで表現すると、

merge_df(3)=pd.merge(merge_df(2), make_df(ym_list[2], on='会社', how='outer')

のようになります。

merge_df(2)の部分について考えます。merge_df(1)を使えることを意識すると、

(merge_df(1))と(df2)をmergeしたデータフレーム

と表現できます。

merge_df(1)は1つのデータフレームを結合することになるので、df1を出力させておけば良さそうです。

つまり、merge_df(n)において、n=1のときにはmake_df(ym_list[0])とします。

よって、

(merge_df(1))と(df2)をmergeしたデータフレーム

は以下のように書き換えられます。

(make_df(ym_list[0])と(make_df(ym_list[1])をmergeしたデータフレーム

結局、merge_df(3)は、df1・df2・df3を結合したデータフレームを作成する関数であることが確認できました。

merge_df(n)についての関数を定義する際のイメージ図

▲merge_df(n)についての関数を定義する際のイメージ図です。

これまでの事を踏まえて、再帰関数とPandasのmergeを使って 3つ以上のDataFrameを結合する全体のコードは以下のようになります。

ym_list = ['202106', '202107', '202108']
def make_df(ym_list):
    df = pd.read_csv('sample_' + ym_list + '.csv')
    df.columns = ['会社', ym_list]
    return df

def merge_df(n: int): #結合するデータフレームの個数をnとする
    if n < 1: 
        return 0 
    elif n == 1:
        return make_df(ym_list[0])
    else:
        return pd.merge(merge_df(n-1), make_df(ym_list[n-1]) ,on='会社',how='outer')
merge_df(len(ym_list))

ym_listの長さは3つなので、merge_df(len(ym_list))は3つのデータフレームが結合された出力結果になるはずです。

3つ以上のDataFrameを再帰関数とmergeを使って結合するイメージ図

▲merge_df(3)の出力結果。3つのデータフレームを結合できています。

n=1のときは、初期値として、make_df(ym_list[0])を出力するようにしています。

n<1の値が出力された場合は無限ループにならないように、意図的にエラーが発生するようにしています。

再帰関数とPandasのmergeを使って3つ以上のDataFrameを結合する方法についての紹介でした。

参考 pandas.merge — pandas 1.3.5 documentation

コメント

タイトルとURLをコピーしました