データセットの結合② pandas.merge()

データセットの結合② pandas.merge()

pandas.merge()

 pandas.merge() はデータセットを横方向に連結し、重複項目を適切な形で保存する機能をもっています。

キーの自動選択

 具体例を使って説明します。最初に社員ID、氏名・年齢・所属部署が記録されたデータフレームを作成しておきます。

# リストPD28-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 とだけ記述すると、きれいな表が出力されます。次は各部署の部門管理者 (部長) を記載したデータフレームを作成します。

# リストPD28-2

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

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

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

# リストPD28-3

# 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 つ以上あるときなど、キーの自動選択機能がうまくはたらかないときがあります。たとえば次のように、ある学校で実施された数学と英語の試験結果が別々のデータフレームに記録されているとします。

# リストPD29-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キーワード を使用します。たとえば、"氏名" をキーとして連結するならば、次のようなコードを書きます。

# リストPD29-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属性にアクセスします。

# リストPD29-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キーワードで列ラベルの接尾辞を指定できます。たとえば、リストPD29-1 の df_m と df_e を連結して、数学と英語の点数を "点数(数学)", "点数(英語)" にしたい場合は次のように記述します。

# リストPD29-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, 氏名, 部署を記載した名簿を作成します。

# リストPD30-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 と年齢を記載した表を作ります。

# リストPD30-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 で指定します。

# リストPD30-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()メソッドで削除します。

# リストPD30-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

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

# リストPD31-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  京子さんの椅子      沖野翔三

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

# リストPD31-2

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

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

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

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

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

# リストPD31-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 で埋めます。

# リストPD31-4

# 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