【Python初心者向け】PandasでDataFrameをマージ・結合する方法

今回はPandasのDataFrameをマージ・結合する方法について解説していきます。

この記事で使用するデータはこちらに格納してありますので事前にダウンロードしておいてください。

また、DataFrameの作成方法やCSVデータの読み込み方法についてはこちらの記事で解説していますので、わからない方は事前に確認しておいてください。

【Python初心者向け】PandasでDataFrameの作成とCSV読み込み方法の解説

DataFrame同士を縦に結合

まずは結合するデータを読み込みましょう。今回のサンプルデータは各CSVとも「name(名前)」「age(年齢)」「sex(性別)」「birthday(生年月日)」のカラムを持つ10行のデータになります。

user_group_a = pd.read_csv('user_group_a.csv')
user_group_b = pd.read_csv('user_group_b.csv')

user_group_a

name age sex birthday
0 及川 22 1998/5/25
1 上島 32 1987/12/19
2 小塚 41 1979/3/3
3 吉村 22 1998/7/31
4 川越 33 1986/11/13

user_group_b

name age sex birthday
0 品川 37 1982/12/5
1 千野 52 1967/9/28
2 北野 59 1961/5/5
3 今西 24 1996/3/7
4 36 1983/11/30

上記の2つのDataFrameを縦に結合してみましょう。DataFrameを縦に結合するにはconcat関数を使います。concat関数には結合したいDataFrameをリストにしたものを引数に入れます。

users = pd.concat([user_group_a, user_group_b])
name age sex birthday
0 及川 22 1998/5/25
1 上島 32 1987/12/19
2 小塚 41 1979/3/3
3 吉村 22 1998/7/31
4 川越 33 1986/11/13
0 品川 37 1982/12/5
1 千野 52 1967/9/28
2 北野 59 1961/5/5
3 今西 24 1996/3/7
4 36 1983/11/30

これで簡単にDataFrameを結合することができました。ただ、これだと見ての通り、Index(行番号)が重複してしまっているため、後々の処理で都合が悪いです。結合時にIndex(行番号)を再度割り振るにはignore_indexという引数を渡します。

users = pd.concat([user_group_a, user_group_b], ignore_index=True)
name age sex birthday
0 及川 22 1998/5/25
1 上島 32 1987/12/19
2 小塚 41 1979/3/3
3 吉村 22 1998/7/31
4 川越 33 1986/11/13
5 品川 37 1982/12/5
6 千野 52 1967/9/28
7 北野 59 1961/5/5
8 今西 24 1996/3/7
9 36 1983/11/30
解説
  • DataFrameを縦に結合するには、DataFrameのリストをconcat関数に入れる
  • 結合時にIndexを付け替えるにはignore_index=Trueを引数に指定する。(デフォルトではignore_index=False)

階層インデックス(MultiIndex)

階層インデックスとは、その名の通り、インデックスを階層的に管理することができるようになります。

上記の例ではインデックスが0~9といったような、連続する行番号的な意味を持ったインデックスになっています。これの上位階層として、各グループに対してインデックスを付与することが可能です。まずは例をみてみてください。

users = pd.concat([user_group_a, user_group_b], keys=['group_a', 'group_b'])
name age sex birthday
group_a 0 及川 22 1998/5/25
1 上島 32 1987/12/19
2 小塚 41 1979/3/3
3 吉村 22 1998/7/31
4 川越 33 1986/11/13
group_b 0 品川 37 1982/12/5
1 千野 52 1967/9/28
2 北野 59 1961/5/5
3 今西 24 1996/3/7
4 36 1983/11/30

contan関数にkeysという引数を指定することで、各DataFrameごとにインデックスを付与することができます。こうすることで、DataFrameを結合しつつ、元のユーザーグループがどれに当てはまるのかがわかるようになります。

例えば、DataFrameを結合後にuser_group_bだけを抽出したい場合は下記のようにします。

users.loc['group_b']
name age sex birthday
0 品川 37 1982/12/5
1 千野 52 1967/9/28
2 北野 59 1961/5/5
3 今西 24 1996/3/7
4 36 1983/11/30

結合したusersというDataFrameから「loc[‘group_b’]」と指定することでuser_gruop_bのデータを抽出することができました。結構便利なので覚えておいて損はないと思います。

appendによる結合

縦に結合する方法のもう一つにappned関数があります。こちらでもconcat同様にDataFrameを結合することができます。

users = user_group_a.append(user_group_b)
name age sex birthday
0 及川 22 1998/5/25
1 上島 32 1987/12/19
2 小塚 41 1979/3/3
3 吉村 22 1998/7/31
4 川越 33 1986/11/13
0 品川 37 1982/12/5
1 千野 52 1967/9/28
2 北野 59 1961/5/5
3 今西 24 1996/3/7
4 36 1983/11/30

 

DataFrameを横に結合

次はDataFrameを横に結合する方法について解説していきます。

今度は生徒の一覧のDataFrame(students)に対して、点数表(points)のDataFrameを紐付けてみましょう。

students = pd.DataFrame({
    'name': ['品川', '千野', '北野', '今西', '金'],
    'sex': ['男', '女', '女', '男', '女']
})
name sex
0 品川
1 千野
2 北野
3 今西
4
points = pd.DataFrame({
    'name': ['千野', '北野', '山田'],
    'point': [40, 80, 60]
}, index=[1, 2, 5])
name point
1 千野 40
2 北野 80
5 山田 60

こちらのデータを使って「外部結合」と「内部結合」のやり方について解説していきます。

DataFrameの外部結合

外部結合は2つのDataFrameを同じインデックスをもとに結合する方法の一つで、インデックスの値が一致するものと、一致しないものの両方を結合することができます。SQLを書いたことがある場合、「OUTER JOIN」がこれに該当します。

result = pd.concat([students, points], axis=1, join='outer')
name sex name point
0 品川 NaN NaN
1 千野 千野 40.0
2 北野 北野 80.0
3 今西 NaN NaN
4 NaN NaN
5 NaN NaN 山田 60.0
解説
  • axis=1を指定することで横に結合することができます。デフォルトはaxis=0となっており、縦の結合となります。
  • 外部結合をする場合は、join=’outer’と指定します。
  • pointsのDataFrameにはインデックス1, 2, 5のデータが存在しており、それぞれインデックスに対応したstudentsのDataFrameにデータが結合されていることがわかります。pointsのDataFrameに存在しない場合は、NaNで補完されます。

内部結合

次は内部結合のやり方について解説します。

外部結合はインデックスが一致しないものも出力するのに対し、内部結合はインデックスが一致するものだけの結果を取得することができます。SQLでいうところの「INNER JOIN」になります。

result = pd.concat([students, points], axis=1, join='inner')
name sex name point
1 千野 千野 40
2 北野 北野 80
解説
  • 内部結合をする場合は、join=’inner’と指定します。
  • students, pointsの各DataFrameに存在するインデックスのデータのみ結果を取得することができます。

merge関数を使った結合

最後にmerge関数の使い方について解説していきます。

concatの結合はインデックスをキーに同様のインデックス持ったデータ同士を結合するのに対し、merge関数はDataFrameの指定したカラムをキーに結合することができます。よりSQLライクにDataFrame同士を結合することができます。今度は下記のCSVを読み込んでみてください。

students = pd.read_csv('students.csv')
id name sex
0 1 詩織
1 2 楓華
2 3 雅也
3 4 比呂
4 5 梨乃
points = pd.read_csv('points.csv')
id point
0 2 40
1 3 80
2 6 60

外部結合

pd.merge(students, points, how='outer', on=['id'])
id name sex point
0 1 詩織 NaN
1 2 楓華 40.0
2 3 雅也 80.0
3 4 比呂 NaN
4 5 梨乃 NaN
5 6 NaN NaN 60.0
解説
  • 外部結合をするにはhow=’outer’と指定します。
  • onの引数に結合するためのキーを指定します。複数キーがある場合は複数指定してください。

内部結合

pd.merge(students, points, how='inner', on=['id'])
id name sex point
0 2 楓華 40
1 3 雅也 80
解説
  • 内部結合をするにはhow=’outer’と指定します。

ちなみに上記のmerge関数をSQLで表すと下記のようになります。

SELECT students.*, points.point FROM students INNER JOIN points ON students.id = points.id;