In [1]: import pandas as pd
In [2]: df1 = pd.DataFrame({'A' : [ 'A0', 'A1', 'A2', 'A3'],
...: 'B' : [ 'B0', 'B1', 'B2', 'B3']},
...: index = [0, 1, 2, 3])
In [3]: df2 = pd.DataFrame({'A' : ['A4','A5', 'A6'],
...: 'C' : ['C4','C5', 'C6']},
...: index = [4,5,6])
In [4]: pd.concat([df1, df2])
Out[4]:
A B C
0 A0 B0 NaN
1 A1 B1 NaN
2 A2 B2 NaN
3 A3 B3 NaN
4 A4 NaN C4
5 A5 NaN C5
6 A6 NaN C6
このように結合されます。
列ラベルの値が一致するもの同士が結合されます。
列ラベルの値が存在しない所のデータはNaN値で返されます。
結合の方向を指定する
デフォルトでは縦方向の結合でしたが、今度は横方向で結合してみましょう。
axis引数を設定することで変更可能です。
In [7]: df3 = pd.DataFrame({'C' : ['C0', 'C1', 'C2', 'C4'],
...: 'D' : ['D0', 'D1', 'D2', 'D4']},
...: index=[0, 1, 2, 4])
In [8]: pd.concat([df1, df3], axis=1) # もしくはaxis='columns'
Out[8]:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 NaN NaN
4 NaN NaN C4 D4
データを連結する際新たにインデックスラベルを0から振り直したい場合はignore_index=Trueにするとできます。
In [11]: df4 = pd.DataFrame({'A':['A0','A1','A3'],
...: 'B':['B0','B1','B3']},index=['K0','K1','K3'])
In [12]: df5 = pd.DataFrame({'A':['A2','A4','A5'],
...: 'B':['B2','B4','B5']},index=['L0','L1','L2'])
In [13]: pd.concat([df4,df5],ignore_index=True)
Out[13]:
0 A0 B0
1 A1 B1
2 A3 B3
3 A2 B2
4 A4 B4
5 A5 B5
横方向ですと列ラベルが0から振り直されます。
In [10]: pd.concat([df1, df3], ignore_index=True, axis='columns') # 横方向
Out[10]:
0 1 2 3
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 NaN NaN
4 NaN NaN C4 D4
被りのある列ラベル(インデックス)が存在していたとしても、これで判別可能です。
In [16]: pd.concat([df1, df2],keys=['df1','df2'])
Out[16]:
A B C
df1 0 A0 B0 NaN
1 A1 B1 NaN
2 A2 B2 NaN
3 A3 B3 NaN
df2 4 A4 NaN C4
5 A5 NaN C5
6 A6 NaN C6
横方向でもできます。
In [17]: pd.concat([df1, df3],axis=1,keys=['df1','df3'])
Out[17]:
df1 df3
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 NaN NaN
4 NaN NaN C4 D4
join引数で結合した結果に含まれるラベルの範囲を指定します。
デフォルトではjoin='outer'になっているため、ラベルがどれか1つでも含まれていれば結合した結果のラベルにも含まれていることになります。
join='inner'に変えることで全てのデータに含まれているラベルのみで構成することができます。
In [18]: pd.concat([df1, df2],join='inner') # A列しか被っていないのでA列だけが表示される
Out[18]:
0 A0
1 A1
2 A2
3 A3
4 A4
5 A5
6 A6
次は横方向です。
In [20]: pd.concat([df1, df3],join='inner',axis=1) # 横方向
Out[20]:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
join_axesで具体的な値を指定することができます。
join_axes=[df1.index]と指定すればdf1のインデックスのラベルのみを使用することになります。
In [21]: pd.concat([df1, df2],join_axes=[df1.columns]) # df1のカラムラベルを使う
Out[21]:
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3
4 A4 NaN
5 A5 NaN
6 A6 NaN
横方向でもできます。
In [23]: pd.concat([df1, df3],axis=1, join_axes=[df3.index]) # df3のインデックスラベルのみを使用する
Out[23]:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
4 NaN NaN C4 D4
今回は柔軟な結合を実現するconcat関数の使い方について解説しました。
引数名がややこしいものがありそれらは実際に使って見て感覚を掴む方がイメージがつきやすいと思うので手を動かして覚えていけば良いかと思います。
使い方のイメージとしてはjoin関数のaxisが指定できるようになったバージョンという感じで、結合する際に使用する紐付けを個別に設定できないというところに違いがあります。
これらを使いこなして、データ結合を楽にできるようになりましょう。
Python for Data Analysis 2nd edition –Wes McKinney(書籍)
pandas.concat - pandas 0.23.4 documentation
Merge, join, and concatenate — pandas 0.23.4 documentation