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_on と right_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
コメント
他のデータベース言語にはあるのだろうが、初めてデータフレームの merge 機能を使ってみてこれは使える、使えそうな場面をいくつかすぐに思いつきました。作成したデータフレーム名を入力するだけできれいな表形式で表示され、インタラクティブ・テーブルに変換するコンバート・ボタンをクリックすれば、データの並べ替えや検索が自由にできるうえに、CSV/JSON/MARKDOWN形式に変換するコピー機能まで付いているのは驚きでした。
Google Colab のインタラクティブ・テーブルのことは全然知りませんでした。少し試してみたのですが、これはいいですね! シンプルなレイアウトで使いやすいですし、ワンクリックでファイル変換できる手軽さも魅力です。Google Colab ノートブックを共有すれば、チームでデータベースを運用することもできそうです。良い機能を教えてくださってありがとうございます!