Pandas入門講座|11.データの結合方法(merge)【PythonのライブラリPandas】

はじめに

こんにちは。キノコードです。
この動画では、Pandas主にデータフレームの結合の方法について学びます。
結合とは、2つのデータフレームをくっつけることです。
Pandasによる結合の方法はいくつかありますが、ここではmergeメソッドについて説明します。
mergeメソッドは、SQLのjoinやExcelのVlookupと似ています。
例えば、AさんからEさんまで、数学の点数が記録されたデータフレームと、国語の点数が記録されたデータフレームがあったとします。
Pandasでは2つのデータフレームを左のデータフレームと右のデータフレームとして考えます。
この2つのデータフレームが名前の部分が一致していますよね。
この名前の部分を共通キーに2つのデータフレームを結合をします。
そして、名前の部分は共通部分なので、片方の名前のカラムが消え、2つのデータフレームが1つになったデータフレームができあがります。
それではパソコン画面に切り替えてレッスンを進めていきます。

データフレームの作成

import pandas as pd

まず、Pandasをインポートする記述をします。
「as」を使ってPandasを「pd」という名前で使えるようにしましょう。
実行します。

df01 = pd.DataFrame( {‘氏名’:[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘数学’:[1, 2, 3, 4]})
df01

ライブラリのインポートが終わったところで、データフレームを作成しましょう。
2つのデータフレームを結合するので、まず1つ目のデータフレームを作成します。
a001という学級の高橋さん、伊藤さん、鈴木さん、佐藤さんが受けた数学のテスト結果のデータフレームを作成しましょう。
点数は、わかりやすさのために1234とします。実行します。このようなデータフレームです。

df02 = pd.DataFrame( {‘氏名’:[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘国語’:[5, 6, 7, 8]})
df02

次に、同じクラスの同じ名前の人が国語のテストを受けた結果のデータフレームを作成しましょう。
テストの点数は、それぞれ5678とします。
実行します。

同じ名前のカラムをキーに結合

pd.merge(df01 ,df02, on=’氏名’)

それでは早速、df01とdf02のテーブルを結合させてみましょう。
pd.mergeと書いて丸括弧を書きます。第一引数に左のデータフレーム、第二引数に右のデータフレームを書きます。onの引数には結合させるのキーとなるカラム名を記述しましょう。
この2つのデータフレームでキーとなるのは「氏名」なので、氏名を指定します。
実行します。結合できました。

重複カラム名の指定方法

pd.merge(df01 ,df02, on=’氏名’, suffixes=[‘_left’, ‘_right’])

氏名のキーは共通キーなので2つのカラムが1つになりました。
しかし、クラスのカラムはどちらのデータフレームにもあるカラムなので、左のデータフレームのクラスには_xがつき、右のデータフレームのクラスには_yがついています。
_xや_yという名前ではわかりにくいなどの場合は、任意の名前に変更することができます。
suffixesという引数にリストでそれぞれの名前を渡しましょう。
今回は左のデータフレームのカラムには_leftという名前をつけ、右のデータフレームには_rightという名前をつけましょう。実行します。名前がつきました。

pd.merge(df01 ,df02, on=’氏名’, suffixes=[”, ‘_重複’])

今度は、リストの1番目をシングルクオテーション2つにします。
これで何もない値を渡していることになります。
2番目のリストの値を_重複とします。

異なるカラム名をキーに結合

df= pd.merge(df01 ,df02, on=’氏名’, suffixes=[”, ‘_重複’])
df
df.columns
new_col = [s for s in df.columns if not ‘重複’ in s]
new_col
df[new_col]
df02_name = pd.DataFrame( {‘名前’:[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘国語’:[5, 6, 7, 8]})
df02_name

カラム名が違うもの同士で結合した場合はどうすればよいでしょうか?
先ほど見たdf02のデータフレームの氏名を名前に変更したデータフレームを作成しましょう。
そのデータフレームをdf02_nameという変数に代入します。

pd.merge(df01 ,df02_name, left_on=’氏名’,right_on=’名前’)

カラム名を違うもの同士で結合したい場合、左のデータフレームのカラムをleft_onという引数に渡して、右のデータフレームのカラム名をright_onという引数に渡します。
今回は、left_onに氏名、right_onに名前を渡しましょう。
実行します。
違うカラム名をキーに結合することができました。

複数のキーで結合

df03 = pd.DataFrame( {‘名前’:[‘高橋’, ‘高橋’],
‘クラス’:[‘a001′,’a002’],
‘英語’:[15, 16]})
df03

結合したいキーが一意ではなく、2つのカラムがセットで一意になる場合はどのようにしたらいいでしょうか?
つまり、2つのカラムをキーに結合する場合です。
ちなみに、一意とは、すべての値が重複しないことをいいます。
例えば、「A、B、C、D、E」のアルファベット一意と言えます。
一方、「A、A、B、B、C」のアルファベットは、AとBが重複しているため、一意ではありません。
なお、一意のことをユニークとも言います。
プログラミングをしていると、よく使う用語なので覚えておきましょう。
a001というクラスに高橋さんがいて、a002というクラスにも高橋さんがいたとします。
ただし、名前とクラスをセットにすると一意になります。つまり、a001クラスの高橋さんと言えば、一人しかいなくて特定できるとします。
a001とa002の高橋さんがいるデータフレームを作成してみましょう。
このようなデータフレームです。

pd.merge(df01 ,df03, left_on=[‘氏名’,’クラス’],right_on=[‘名前’,’クラス’])

2つのカラムで結合するには、それぞれのカラムをリストで渡します。
左のデータフレームは氏名とクラスのリスト、右のデータフレームは名前とクラスのリストで引数に渡してみましょう。
実行します。結合ができたようです。

結合の種類

左のデータフレームと右のデータフレームで、左のデータフレームにあるデータだけ結合することもできます。
SQLでいうところのleft_joinやright_joinのことです。SQLの経験でいらっしゃればピンとくると思います。
ただ、SQLの経験者ばかりではないと思うので、その結合方法について図をいれて解説します。
結合方法には4つあります。
innerとleftとrightとouterの4つです。
最初にinnerについて説明します。
innerは2つのデータフレームの共通しているキーのみ結合する方法です。
例えば、この場合だとC〜Fが共通しています。
したがって、この共通する行のみ結合します。結合した結果は、このようなデータフレームとなります。
次はleftについてです。
leftは、左のデータフレームをベースに考えます。
左のデータフレームは全部残ります。右のテーブルは共通している部分だけ残ります。右のデータフレームにはないものは、NaNになります。
rightについては、leftと同じイメージです。右のデータフレームは全部残ります。左のテーブルは共通している部分だけ残ります。左のデータフレームにはないものは、NaNになります。
最後にouterです。
outerは共通するデータで結合をして、左のデータフレームにあるものも右のデータフレームにあるものの、そのままにしておく方法です。片方にしかないデータについてはNaNになります。
以上が4つの結合方法の説明です。
では、実際にみてきましょう。

df01 = pd.DataFrame( {‘氏名’:[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘数学’:[1, 2, 3, 4]})
df01
df01のデータフレームはこのようなデータフレームでした。
df04 = pd.DataFrame( {‘氏名’:[‘高橋’, ‘伊藤’, ‘渡辺’, ‘加藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘国語’:[5, 6, 7, 8]})
df04

もう1つデータフレームを作成しましょう。
左のデータフレームと右のデータフレームで、左のデータフレームにあるデータだけ結合することもできます。
df01とは高橋さんと伊藤さんが共通。df04には鈴木さんと佐藤さんがいません。

pd.merge(df01 ,df02, on=’氏名’,how=’left’)

まずleftの結合方法です。
leftの場合は、howという引数にleftを渡します。
実行します。
結合できました。右のデータフレームにないものはNaNになっています。

pd.merge(df01 ,df02, on=’氏名’,how=’right’)

rightの結合方法は、howにrightを渡し

pd.merge(df01 ,df02, on=’氏名’,how=’outer’)

outerの結合方法はhowにouterを渡します。
できています。

pd.merge(df01 ,df02, on=’氏名’,how=’inner’)

ちなみに、デフォルトはinnerになっています。
このように明示的にinnerを記述してもよいですし、

pd.merge(df01 ,df02, on=’氏名’)

記述しなくても同じ結果が返ってきます。

pd.merge(df01 ,df02, on=’氏名’,how=’outer’)

outerの結果はこのようなものでした。
これだとどちらのテーブルのものなのかわからないです。

pd.merge(df01 ,df02, on=’氏名’,how=’outer’, indicator=True)

その場合はindicatorという引数にTrueを渡します。
実行します。そうすると、両方のテーブルにあるものはboth、左のデータフレームのみのものがleft_only、右のデータフレームのみのものはright_onlyとなります。わかりやすいですね。

インデックスをキーに結合

df05 = pd.DataFrame( {‘クラス’:[‘df01’, ‘df01’, ‘df01’, ‘df01’],
‘数学’: [1, 2, 3, 4],
‘国語’:[5, 6, 7, 8]},
index=[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’])

結合キーについてはカラムしか指定することができません。
しかし、データフレームのインデックスを結合キーに使いたい場合があると思います。
その場合の説明をします。
まず、インデックスが名前のデータフレームを作成します。df05という変数にデータフレームを代入します。表示をさせてみると、名前がインデックスになっているのがわかります。

df02 = pd.DataFrame( {‘氏名’:[‘高橋’, ‘伊藤’, ‘鈴木’, ‘佐藤’],
‘クラス’:[‘a001’, ‘a001’, ‘a001’, ‘a001’],
‘国語’:[5, 6, 7, 8]})
df02

次に、df02のデータフレームはこのようなものでした。

pd.merge(df05 ,df02,left_index=True,right_on=’氏名’)

左のデータフレームの結合キーはindexにするには、引数left_indexを使い、Trueを渡します。
実行します。
結合ができています。
右のデータフレームの結合キーがインデックスの場合はleft_indexではなくright_indexにすればよいです。
次のレッスンはconcatというメソッドについてみていきます。
concatはmergerメソッドとは違い、縦方向であっても結合することができます。
また、caocatは、3つ以上のデータフレームを結合することができます。
一方、concatは、2つ以上のカラムをキーに結合することができません。また、結合方法としてinnerとoutetはありますが、leftやrightの結合方法はありません。
したがって、3つ以上のデータフレームを結合したい場合はconcat。2つ以上のカラムをキーに結合した場合やleftやrightで結合したい場合は、mergeメソッドを使うとよいでしょう。
キノコードでは、Pandas入門コースの他に、仕事に活かせるPythonの自動化のレッスン、株のデータ分析のレッスンをアップしています。
また人工知能のレッスンや、Pythonでのグラフの作り方についてのレッスンをアップしていく予定です。
新着通知もいくのでぜひチャンネル登録をお願いします。

レッスンで使ったファイルはこちら

■保存方法
Mac:右クリック⇒「リンク先を別名で保存」
Windows:右クリック⇒「名前を付けてリンク先を保存」

Jupyter Labのファイルはこちら