改訂版 Pythonユーザのための Jupyter[実践]入門 [ 池内 孝啓、片柳 薫子、@driller ]
こんにちは、monachan_papa です。
今回は pandas.DataFrame の連結・結合メソッドである concat、mergeメソッドについて解説します。
これらのメソッドを使うと、まるで SQL のように複数の表データを連結・結合することができます。よって、SQL の知識・経験がある御方ならばすぐにでも使いこなせるであろうメソッドです。
しかし、そうでない御方でも全く問題ありませんし、臆する必要もまるでありません。
本解説を読むことにより、concat、mergeメソッドの違いや使い方が理解でき、複数の表データの連結・結合が自在にできる基礎力が身につきます。
concatメソッド(タテ連結・結合)
concatメソッドは、複数のデータフレームを タテ方向に連結・結合 するメソッドです。
まずは、テストデータを用意します。
import numpy as np
import pandas as pd
# テストデータ1、2
np.random.seed(0)
df1 = pd.DataFrame(np.random.rand(3, 4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.random.rand(2, 4), columns=['A', 'B', 'C', 'D'])
display(df1, df2)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
A | B | C | D | |
---|---|---|---|---|
0 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
1 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
以下の構文で、タテ方向に連結・結合することができます。
ただし、各データフレームは列名が同じ必要があります。
以下のコードは、df1、df2 をタテ方向に連結・結合しています。
# テストデータ確認
display(df1, df2)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
A | B | C | D | |
---|---|---|---|---|
0 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
1 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
# タテ方向に連結・結合
pd.concat([df1, df2])
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
0 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
1 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
タテ方向に連結・結合できました。
しかし、インデックスが古いままになっています。これを更新するには2通りの方法があります。
- ignore_index=True を引数指定
- 連結・結合後に、reset_index(drop=True)メソッド を使用
以下のコードは、ignore_index=True を引数指定して、インデックスを更新しています。
# テストデータ
display(df1, df2)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
A | B | C | D | |
---|---|---|---|---|
0 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
1 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
# インデックス更新
pd.concat([df1, df2], ignore_index=True)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
3 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
4 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
以下のコードは、連結・結合後に reset_index(drop=True)メソッドを使って、インデックスを新しくしています。
# テストデータ確認
display(df1, df2)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
A | B | C | D | |
---|---|---|---|---|
0 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
1 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
# インデックス更新
pd.concat([df1, df2]).reset_index(drop=True)
A | B | C | D | |
---|---|---|---|---|
0 | 0.548814 | 0.715189 | 0.602763 | 0.544883 |
1 | 0.423655 | 0.645894 | 0.437587 | 0.891773 |
2 | 0.963663 | 0.383442 | 0.791725 | 0.528895 |
3 | 0.568045 | 0.925597 | 0.071036 | 0.087129 |
4 | 0.020218 | 0.832620 | 0.778157 | 0.870012 |
mergeメソッド(ヨコ連結・結合)
mergeメソッドは複数のデータフレームを ヨコ方向に連結・結合 するメソッドです。
まずは、テストデータを用意します。
# テストデータ1〜3
np.random.seed(0)
df1 = pd.DataFrame(np.random.rand(3, 2), columns=['A', 'B'])
df2 = pd.DataFrame(np.random.rand(3, 2), columns=['A', 'B'])
df3 = pd.DataFrame(np.random.rand(3, 2), columns=['A', 'B'])
df1['C'] = ['たけし', 'さんま', 'タモリ']
df2['C'] = ['たけし', 'さんま', '志村']
df3['F'] = ['志村', '加ト', 'いかりや']
display(df1, df2, df3)
A | B | C | |
---|---|---|---|
0 | 0.548814 | 0.715189 | たけし |
1 | 0.602763 | 0.544883 | さんま |
2 | 0.423655 | 0.645894 | タモリ |
A | B | C | |
---|---|---|---|
0 | 0.437587 | 0.891773 | たけし |
1 | 0.963663 | 0.383442 | さんま |
2 | 0.791725 | 0.528895 | 志村 |
A | B | F | |
---|---|---|---|
0 | 0.568045 | 0.925597 | 志村 |
1 | 0.071036 | 0.087129 | 加ト |
2 | 0.020218 | 0.832620 | いかりや |
ヨコ連結・結合については、色々なパターンがあるので、以降で詳しく見ていきます。
改訂版 Pythonユーザのための Jupyter[実践]入門 [ 池内 孝啓、片柳 薫子、@driller ]
内部結合
内部結合はキーとなる列を見て、その列内でおいて値が一致するデータだけを連結・結合します。
以下の構文で、内部結合ができます。
以下のコードは、df1 と df2 において、C列をキーに内部結合をしています。
# テストデータ確認
display(df1, df2)
A | B | C | |
---|---|---|---|
0 | 0.548814 | 0.715189 | たけし |
1 | 0.602763 | 0.544883 | さんま |
2 | 0.423655 | 0.645894 | タモリ |
A | B | C | |
---|---|---|---|
0 | 0.437587 | 0.891773 | たけし |
1 | 0.963663 | 0.383442 | さんま |
2 | 0.791725 | 0.528895 | 志村 |
# 内部結合
pd.merge(df1, df2, on='C')
A_x | B_x | C | A_y | B_y | |
---|---|---|---|---|---|
0 | 0.548814 | 0.715189 | たけし | 0.437587 | 0.891773 |
1 | 0.602763 | 0.544883 | さんま | 0.963663 | 0.383442 |
C列で値が一致している、「たけし、さんま」のデータだけが連結・結合されました。
それ以外は切り捨てられます。
列名が異なる場合の内部結合
さきほどの内部結合では、C列 という共通した列がありました。
しかし、共通した列名がない場合でも内部結合は可能です。
以下の構文で、列名が異なる場合の内部結合ができます。
以下のコードでは、df2 と df3 において df2 の C列、df3 の F列 をキーに内部結合をしています。
# テストデータ確認
display(df2, df3)
A | B | C | |
---|---|---|---|
0 | 0.437587 | 0.891773 | たけし |
1 | 0.963663 | 0.383442 | さんま |
2 | 0.791725 | 0.528895 | 志村 |
A | B | F | |
---|---|---|---|
0 | 0.568045 | 0.925597 | 志村 |
1 | 0.071036 | 0.087129 | 加ト |
2 | 0.020218 | 0.832620 | いかりや |
# 列名が異なる場合の内部結合
pd.merge(df2, df3, left_on='C', right_on='F')
A_x | B_x | C | A_y | B_y | F | |
---|---|---|---|---|---|---|
0 | 0.791725 | 0.528895 | 志村 | 0.568045 | 0.925597 | 志村 |
C列、F列で値が一致している「志村」のデータだけが連結・結合されました。
それ以外は切り捨てられます。
外部結合
さきほど解説した2種類の内部結合では、キーとなる列を見て、その列において値が一致するデータだけを連結・結合しました。
そして、値が一致していないデータは切り捨てられていました。
しかし、「値が一致していなくても、切り捨てて欲しくないシーンもある。」
その要求に応えるのが、外部結合と呼ばれる連結・結合です。
以下の構文で、外部結合ができます。
なお、外部結合には、左外部結合と右外部結合 があります。
引数how に left または right を指定することで、どちらにするか切替可能です。
左外部結合
- 左側である df1 については、すべてデータが残る
- 右側である df2 については、値が一致しないデータは欠損値扱いとなる
右外部結合
- 右側である df2 については、すべてデータが残る
- 左側である df1 については、値が一致しないデータは欠損値扱いとなる
まずは、左外部結合の例です。
以下のコードは、df1 と df2 において、C列をキーに左外部結合をしています。
# テストデータ確認
display(df1, df2)
A | B | C | |
---|---|---|---|
0 | 0.548814 | 0.715189 | たけし |
1 | 0.602763 | 0.544883 | さんま |
2 | 0.423655 | 0.645894 | タモリ |
A | B | C | |
---|---|---|---|
0 | 0.437587 | 0.891773 | たけし |
1 | 0.963663 | 0.383442 | さんま |
2 | 0.791725 | 0.528895 | 志村 |
# 左外部結合
pd.merge(df1, df2, how='left', on='C')
A_x | B_x | C | A_y | B_y | |
---|---|---|---|---|---|
0 | 0.548814 | 0.715189 | たけし | 0.437587 | 0.891773 |
1 | 0.602763 | 0.544883 | さんま | 0.963663 | 0.383442 |
2 | 0.423655 | 0.645894 | タモリ | NaN | NaN |
左側である df1 については、すべてのデータがあります。
一方、右側である df2 については、「タモリ」に一致するデータがないものは、欠損値扱いとなっています。
続いて、右外部結合の例です。
以下のコードは、df1 と df2 において、C列をキーに右外部結合をしています。
# テストデータ確認
display(df1, df2)
A | B | C | |
---|---|---|---|
0 | 0.548814 | 0.715189 | たけし |
1 | 0.602763 | 0.544883 | さんま |
2 | 0.423655 | 0.645894 | タモリ |
A | B | C | |
---|---|---|---|
0 | 0.437587 | 0.891773 | たけし |
1 | 0.963663 | 0.383442 | さんま |
2 | 0.791725 | 0.528895 | 志村 |
# 右外部結合
pd.merge(df1, df2, how='right', on='C')
A_x | B_x | C | A_y | B_y | |
---|---|---|---|---|---|
0 | 0.548814 | 0.715189 | たけし | 0.437587 | 0.891773 |
1 | 0.602763 | 0.544883 | さんま | 0.963663 | 0.383442 |
2 | NaN | NaN | 志村 | 0.791725 | 0.528895 |
右側である df2 については、すべてのデータがあります。
一方、左側である df1 については、「志村」に一致するデータがないものは、欠損値扱いとなっています。
以上で、pandas.DataFrame 連結・結合メソッドの concat、merge についての解説を終わります。
連結・結合が自在にできると、データ加工・データ分析がとても捗ります。
ここで紹介したのは連結・結合の基本になりますが、この基本が使いこなせているかどうかだけでもかなり違います。
是非、連結・結合の名人を目指して頑張ってください。
さて、pandas をもっともっと使いこなしたい御方、さらにスキルアップをしてみたい御方は改訂版 Pythonユーザのための Jupyter[実践]入門 [ 池内 孝啓、片柳 薫子、@driller ]がたいへんオススメです。
Jupyter Lab のフル活用方法や、データ分析についてのノウハウも同時に学べて一石二鳥ならぬ、一石三鳥です。
もちろん、初心者にも大変オススメできます。Jupyter Lab自体がインタラクティブな動作確認や視覚効果が本当にすばらしいので、プログラミング学習においての理解度が触るたびに上がっていきます。どんどん触ってPython大好き人間になってもらいたいです。
改訂版 Pythonユーザのための Jupyter[実践]入門 [ 池内 孝啓、片柳 薫子、@driller ]
また、爆速で pandas を学びたい御方にはプログラミングスクールを考えるのも、ひとつの手です。独学よりも効果が出やすいですが、いかんせん投資がけっこうかかります。しかし、techgymというスクールは通うか通わないかは別として、無料のサンプルテキスト&解説動画がもらえます。これをとりあえず getしてまずは試しに体験学習するのもありでしょう。
コメント