『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

pandas.merge()

≪【前の記事】pandas.concat()

pandas.mergeでDataFrameを横方向に連結する

pandas.merge() はデータセットを横方向に連結し、重複項目を適切な形で保存する機能をもっています。具体例を使って説明します。最初に社員ID、氏名・年齢・所属部署が記録されたデータフレームを作成しておきます。

# PANDAS_MERGE

# In[1]

import numpy as np
import pandas as pd

# 社員ID
i_d = [105, 109, 203, 211, 307]

# 氏名
name = ["筈山亜希子", "砂田夏樹", "谷古ゆうみ", "棚森亮輔", "南島円華"]

# 年齢
age = [31, 26, 35, 29, 25]

# 所属部署
department = ["営業", "営業", "経理", "経理", "総務"]

# 社員IDを行ラベルとする名簿を作成
df1 = pd.DataFrame({"ID":i_d, "氏名":name, "年齢":age, "部署":department})

print(df1)
#    ID   氏名       年齢  部署
# 0  105  筈山亜希子  31   営業
# 1  109  砂田夏樹    26   営業
# 2  203  谷古ゆうみ  35   経理
# 3  211  棚森亮輔    29   経理
# 4  307  南島円華    25   総務

Jupyter Notebook を使用している場合は、最後の行で print()関数を使わずに df1 とだけ記述すると、きれいな表が出力されます。次は各部署の部門管理者(部長)を記載したデータフレームを作成します。

# In[2]

# 部署と部門管理者(部長)
df2 = pd.DataFrame({"部署":["営業", "経理", "総務"],
                    "管理者":["飛奈貴文", "薬師丸忠行", "塔本果子"]})

print(df2)
#    部署  管理者
# 0  営業  飛奈貴文
# 1  経理  薬師丸忠行
# 2  総務  塔本果子

pandas.merge() を使って、df1 と df2 を結合します。

# In[3]

# pandas.mergeでDataFrameを結合する
df3 = pd.merge(df1, df2)

print(df3)
#    ID   氏名        年齢  部署   管理者
# 0  105  筈山亜希子   31   営業   飛奈貴文
# 1  109  砂田夏樹     26   営業   飛奈貴文
# 2  203  谷古ゆうみ   35   経理   薬師丸忠行
# 3  211  棚森亮輔     29   経理   薬師丸忠行
# 4  307  南島円華     25   総務   塔本果子

df1 と df2 は列ラベル “部署” が共通しているので、pandas.merge() は自動的に “部署” ラベルをキーとして新しい表を作ります。また、所属部署の要素が一部重複しているので、管理者氏名を必要なだけ繰り返し記載しています。

onキーワード

同じラベル名が 2 つ以上あるときには、pandas.merge() のキー自動選択機能がうまくはたらかないときがあります。たとえば次のように、ある学校で実施された数学と英語の試験結果が別々のデータフレームに記録されているとします。

# PANDAS_MERGE_ON

# In[1]

import numpy as np
import pandas as pd

# 氏名
name_m = ["都橋正", "早滝駿太", "花沢綾夏", "馬見塚ゆりこ", "仲宗根泰知"]
name_e = ["馬見塚ゆりこ", "都橋正", "仲宗根泰知", "花沢綾夏", "早滝駿太"]

# 順位
rank = [1, 2, 3, 4, 5]

# 数学のスコア
score_m = [88, 81, 75, 60, 59]

# 英語のスコア
score_e = [95, 84, 63, 59, 42]

df_m = pd.DataFrame({"氏名":name_m, "点数":score_m})
df_e = pd.DataFrame({"氏名":name_e, "点数":score_e})

print("数学の成績\n",df_m, "\n")
print("英語の成績\n",df_e)

'''
数学の成績
   氏名         点数
0  都橋正        88
1  早滝駿太      81
2  花沢綾夏      75
3  馬見塚ゆりこ  60
4  仲宗根泰知    59 

英語の成績
   氏名         点数
0  馬見塚ゆりこ  95
1  都橋正        84
2  仲宗根泰知    63
3  花沢綾夏      59
4  早滝駿太      42
'''

pandas.merge() に df_m と df_e を渡すだけでは何も表示されません。このようなときは、キーとなるラベルを明示する onキーワード を使用します。たとえば、”氏名” をキーとして連結するならば、次のようなコードを書きます。

# In[2]

# "氏名"をキーにデータフレームを連結
df_me = pd.merge(df_m, df_e, on="氏名")

print(df_me)
#    氏名        点数_x  点数_y
# 0  都橋正        88      84
# 1  早滝駿太      81      42
# 2  花沢綾夏      75      59
# 3  馬見塚ゆりこ  60      95
# 4  仲宗根泰知    59      63

df_m の “点数” と df_e の “点数” は別のデータなので、接尾辞を添えて区別されています。列ラベルを変更する場合は columns属性にアクセスします。

# In[3]

# 列ラベルを書き換える
df_me.columns = ["氏名", "数学", "英語"]

print(df_me)
#    氏名         数学  英語
# 0  都橋正        88   84
# 1  早滝駿太      81   42
# 2  花沢綾夏      75   59
# 3  馬見塚ゆりこ  60   95
# 4  仲宗根泰知    59   63

接尾辞を変更する場合は、以下で解説する suffixesキーワード を指定します。

suffixesキーワード

suffixesキーワードで列ラベルの接尾辞を指定できます。たとえば、df_m と df_e を連結して、数学と英語の点数を “点数(数学)”, “点数(英語)” にしたい場合は次のように記述します。

# In[4]

# 接尾辞を指定してデータフレームを連結
df_me = pd.merge(df_m, df_e,on="氏名",
                 suffixes=["(数学)", "(英語)"])

print(df_me)
#    氏名      点数(数学)  点数(英語)
# 0  都橋正        88          84
# 1  早滝駿太      81          42
# 2  花沢綾夏      75          59
# 3  馬見塚ゆりこ  60          95
# 4  仲宗根泰知    59          63

left_on, right_onキーワード

ID, 氏名, 部署を記載した名簿を作成します。

# PANDAS_MERGE_LEFT_RIGHT_ON

# In[1]

import numpy as np
import pandas as pd

# 社員ID
id_1 = ["S18", "A30", "A52", "D27", "G04"]

# 氏名
name = ["高石孝介", "門間都", "中積一郎", "二ツ谷端希", "須賀絵理奈"]

# 所属部署
department = ["営業", "経理", "経理", "設計", "総務"]

# データフレームを作成
df4 = pd.DataFrame({"ID":id_1, "氏名":name, "部署":department})

print(df4)
#    ID   氏名        部署
# 0  S18  高石孝介    営業
# 1  A30  門間都      経理
# 2  A52  中積一郎    経理
# 3  D27  二ツ谷端希  設計
# 4  G04  須賀絵理奈  総務

次に ID と年齢を記載した表を作ります。

# In[2]

# 社員ID
id_2 = ["A52", "A30", "D27", "G04", "S18"]

# 年齢
age = [28, 34, 40, 25, 31]

# データフレームを作成
df5 = pd.DataFrame({"社員番号":id_2, "年齢":age})

print(df5)
#    社員番号  年齢
# 0  A52        28
# 1  A30        34
# 2  D27        40
# 3  G04        25
# 4  S18        31

df4 の列ラベル “ID” は df5 の列ラベル “社員番号” に対応しています。しかし、ラベル名が異なっていると pandas.merge() で結合できません。このような場合は、キーにしたいラベルを left_onright_on で指定します。

# In[3]

# df4とdf5を結合
df6 = pd.merge(df4, df5, left_on="ID", right_on="社員番号")

print(df6)
#    ID   氏名        部署  社員番号  年齢
# 0  S18  高石孝介    営業     S18      31
# 1  A30  門間都      経理     A30      34
# 2  A52  中積一郎    経理     A52      28
# 3  D27  二ツ谷端希  設計     D27      40
# 4  G04  須賀絵理奈  総務     G04      25

連結されたデータフレームには “ID” と “社員番号” の列が両方含まれているので、片方を drop()メソッドで削除します。

# In[4]

# "社員番号"の列を削除
df7 = df6.drop("社員番号", axis=1)

print(df7)
#    ID   氏名        部署  年齢
# 0  S18  高石孝介    営業   31
# 1  A30  門間都      経理   34
# 2  A52  中積一郎    経理   28
# 3  D27  二ツ谷端希  設計   40
# 4  G04  須賀絵理奈  総務   25

inner join と outer join

書籍のタイトルと著者が記載された表を作成します。

# PANDAS_MERGE_JOIN

# In[1]

import numpy as np
import pandas as pd

# 書籍のタイトル
title_1 = ["美術館を探して",
           "チョコレートの友情",
           "夫婦ミステリー",
           "ふしぎな青い空",
           "京子さんの椅子"]

# 書籍の著者
author = ["仲邑鷹一",
          "駒田泰秀",
          "宗像悠治",
          "岩井貴弥",
          "沖野翔三"]

# データフレームを作成
book_1 = pd.DataFrame({"タイトル":title_1,
                       "著者":author})

print(book_1)
#    タイトル            著者
# 0  美術館を探して      仲邑鷹一
# 1  チョコレートの友情  駒田泰秀
# 2  夫婦ミステリー      宗像悠治
# 3  ふしぎな青い空      岩井貴弥
# 4  京子さんの椅子      沖野翔三

次に書籍のタイトルと価格を記載した表を作成します。

# In[2]

# 書籍のタイトル
title_2 = ["チョコレートの友情",
           "夫婦ミステリー",
           "京子さんの椅子"]

# 書籍の価格
price = [1290, 840, 1040]

# データフレームを作成
book_2  = pd.DataFrame({"タイトル":title_2,
                        "価格":price})

print(book_2)
#    タイトル            価格
# 0  チョコレートの友情  1290
# 1  夫婦ミステリー       840
# 2  京子さんの椅子      1040

pandas.merge() のデフォルト設定 (how=”inner”) で book_1 と book_2 を連結すると、結果には 2 つのデータの共通部分が含まれます。

# In[3]

# book_1とbook_2を内部結合
book_3 = pd.merge(book_1, book_2)

print(book_3)
#    タイトル            著者      価格
# 0  チョコレートの友情  駒田泰秀  1290
# 1  夫婦ミステリー      宗像悠治   840
# 2  京子さんの椅子      沖野翔三  1040

このように積集合をとる結合方式を内部結合 (inner join) とよびます。how=”outer” を指定すると、外部結合 (outer join) によって和集合を作成し、該当要素がない部分は NaN で埋めます。

# In[4]

# pandas.merge()でbook_1とbook_2を外部結合
book_4 = pd.merge(book_1, book_2, how="outer")

print(book_4)
#    タイトル            著者      価格
# 0  美術館を探して      仲邑鷹一   NaN
# 1  チョコレートの友情  駒田泰秀  1290.0
# 2  夫婦ミステリー      宗像悠治   840.0
# 3  ふしぎな青い空      岩井貴弥   NaN
# 4  京子さんの椅子      沖野翔三  1040.0

≫【次の記事】pandasの集約メソッド

コメント

  1. HNaito より:

    他のデータベース言語にはあるのだろうが、初めてデータフレームの merge 機能を使ってみてこれは使える、使えそうな場面をいくつかすぐに思いつきました。作成したデータフレーム名を入力するだけできれいな表形式で表示され、インタラクティブ・テーブルに変換するコンバート・ボタンをクリックすれば、データの並べ替えや検索が自由にできるうえに、CSV/JSON/MARKDOWN形式に変換するコピー機能まで付いているのは驚きでした。

    • あとりえこばと より:

      Google Colab のインタラクティブ・テーブルのことは全然知りませんでした。少し試してみたのですが、これはいいですね! シンプルなレイアウトで使いやすいですし、ワンクリックでファイル変換できる手軽さも魅力です。Google Colab ノートブックを共有すれば、チームでデータベースを運用することもできそうです。良い機能を教えてくださってありがとうございます!