YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

図解で解決!pandasデータ結合総まとめ(concat, merge, join)

pandasには、データの連結、結合を行うための便利な関数、メソッドがたくさん用意されています。

これらを使いこなせば、自由自在にデータの結合ができるようになる!…はずなのですが…。

実際にデータの結合を行おうとすると、次のような問題に直面することも…

  • 結合関係の関数が多すぎてよくわからない!
  • concat, merge, joinってどれ使えばいいの?!
  • inner, outerとか、内部・外部結合の意味がいまいちよくわからない…

そこで、この記事では、pandasのデータ連結・結合concat, merge, joinについて図解付きで解説していきます!

pandasのデータ結合関数・メソッドまとめ

pandasのデータ連結・結合関連の関数・メソッドには、主に次の3つがあります。

関数・メソッド名 内容 基本的な考え方
concat データの連結 複数のdfをラベル名をもとに連結
merge データの結合 2つのdfの特定のデータ列を基準に結合
join データの結合 複数のdfをインデックス列を基準に結合

引数で結合軸(結合の基準となる列やインデックス)や結合方法(内部結合・外部結合など)を変更できます。

concat, merge, joinの違いと使い分けは?

まずはconcat, merge, joinのざっくりとした考え方を図解で整理してみしょう。

concatは、下図のように同じような構造を持ったdfを連結する際に使用します。

mergejoinは、下図のように特定の列、インデックスをもとにdfを結合する際に使用します。

実際には引数を指定して、mergeでインデックスを、joinでデータ列を結合軸に使用することもできます。

しかし、最初は次のような使い分けでスタートすると良いです。

  • concat:データの連結(シンプルに縦・横にくっつける)
  • merge:データ列を結合軸にしたデータの結合
  • join:インデック列を結合軸にしたデータの結合

以下では、各関数・メソッドの使い方について詳しく解説していきます。

concat|データの連結

concat()関数は、複数データの連結に使用します。

ラベル名をもとにして、データを継ぎ足していくイメージです。

最も基本的な使い方は次の通りです。

連結したいdfをリストや辞書の形式でまとめて、pd.concat()に渡します。

  • pd.concat([dfのリスト]) or
  • pd.concat({dfの辞書})

デフォルト設定では、渡されたdfを縦方向に連結したdfが返されます。

次のサンプルデータで挙動を確認してみましょう。

import pandas as pd

df1 = pd.DataFrame({"名前": ["田中", "佐藤", "鈴木"], 
                    "出身地": ["北海道", "青森", "秋田"], 
                    "チーム": ["チームA", "チームB", "チームB"]}).set_index("名前")
#     出身地   チーム
# 名前           
# 田中  北海道  チームA
# 佐藤   青森  チームB
# 鈴木   秋田  チームB

df2 = pd.DataFrame({"名前": ["後藤", "山田"], 
                    "出身地": ["青森", "宮城"], 
                    "チーム": ["チームB", "チームC"]}).set_index("名前")

#    出身地   チーム
# 名前          
# 後藤  青森  チームB
# 山田  宮城  チームC

リストおよび辞書型にして、それぞれ連結してみます。

# リストで渡す例
pd.concat([df1, df2])
#     出身地   チーム
# 名前           
# 田中  北海道  チームA
# 佐藤   青森  チームB
# 鈴木   秋田  チームB
# 後藤   青森  チームB
# 山田   宮城  チームC

# 辞書で渡す例
pd.concat({"Data1":df1, "Data2":df2})
#           出身地   チーム
#       名前           
# Data1 田中  北海道  チームA
#       佐藤   青森  チームB
#       鈴木   秋田  チームB
# Data2 後藤   青森  チームB
#       山田   宮城  チームC

どちらもデータが縦方向に連結されました。

辞書型の場合はキーをもとにして、インデックスが追加されてMultiindexになっています。

  • 【参考】辞書からのdf生成については次の記事で解説しています。
≫pandas 辞書型からDataFrameを生成|インデックスとコラムの設定も!
pandasでは、辞書型からデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①辞書型からデータフレームを生成する方法、②辞書のキーをインデックス名、コラム名それぞれに設定する方法、③DataFrame()とDataFrame.from_dict()の違いをサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_dict
 

引数による連結方法の設定

concat関数では、引数の指定で連結方法などを変更することができます。

主な設定変更用の引数は次の通りです。

設定内容 引数名 適用
連結方向 axis=0
    or 1
0: 縦方向に連結(デフォルト)
1: 横方向に連結
インデックスの振り直し ignore_index=False
                  or True
False: 振り直しなし(デフォルト)
True: 振り直しあり(0, 1, 2, …の連番)
外部結合・内部結合の設定 join="outer"
    or "inner"
"outer": 外部結合(デフォルト)
"inner": 内部結合

連結方向の設定|axis

デフォルトでは、pd.concat()は縦方向にデータを連結します。

横方向に連結したい場合は、axisを引数を指定します。

  • 縦方向に連結: axis=0(デフォルトなので省略可)
  • 横方向に連結: axis=1

サンプルコードで挙動を確認してみましょう。

# 横方向に使いするデータの用意
df3 = pd.DataFrame({"名前": ["田中", "佐藤", "鈴木"],  
                    "身長": [170, 160, 150], 
                    "体重": [65, 45, 80]}).set_index("名前")
#      身長  体重
# 名前         
# 田中  170  65
# 佐藤  160  45
# 鈴木  150  80

# 横方向に結合
pd.concat([df1, df3], axis=1)
#     出身地   チーム   身長  体重
# 名前                    
# 田中  北海道  チームA  170  65
# 佐藤   青森  チームB  160  45
# 鈴木   秋田  チームB  150  80

インデックスの振り直し|ignore_index

結合後のdfのインデックスを、0, 1, 2, …の連番で振りなおす場合は、ignore_indexを指定します。

  • インデックスの振り直し無し|ignore_index=False(デフォルト)
  • インデックスの振り直しあり|ignore_index=True

サンプルコードで挙動を確認してみましょう。

df_concat = pd.concat([df1, df2], ignore_index=True)
df_concat
#    出身地   チーム
# 0  北海道  チームA
# 1   青森  チームB
# 2   秋田  チームB
# 3   青森  チームB
# 4   宮城  チームC

既存のインデックス列は消滅して、新たに0から始まる連番が振りなおされます。

外部結合・内部結合の設定|join

データの内部結合、外部結合の設定は引数joinで行います。

  • 外部結合: join="outer"
    • 全てのdfのラベルを網羅するように、全データを結合(欠損値はNaNになる)
  • 内部結合: join="inner"
    • 全てのdfにラベルがあるデータのみを結合

図解すると、2つの結合の違いがよくわかります。

次のサンプルデータで外部結合・内部結合の挙動を比較してみす。

df1
#     出身地   チーム
# 名前           
# 田中  北海道  チームA
# 佐藤   青森  チームB
# 鈴木   秋田  チームB

df3 = pd.DataFrame({"名前": ["吉田", "金子"], 
                    "出身地": ["千葉", "東京"],
                    "身長": [170, 180]}).set_index("名前")
#    出身地   身長
# 名前         
# 吉田  千葉  170
# 金子  東京  180

外部結合、内部結合の挙動の違いを確認してみましょう。

#外部結合(デフォルト)
pd.concat([df1, df3])
#     出身地   チーム     身長
# 名前                  
# 田中  北海道  チームA    NaN
# 佐藤   青森  チームB    NaN
# 鈴木   秋田  チームB    NaN
# 吉田   千葉   NaN  170.0
# 金子   東京   NaN  180.0

# 内部結合
pd.concat([df1, df3], join="inner")
#     出身地
# 名前     
# 田中  北海道
# 佐藤   青森
# 鈴木   秋田
# 吉田   千葉
# 金子   東京

外部結合は全てのデータを残すように、内部結合ではラベルが共通のデータのみ結合するようになっていますね。

辞書型で結合する場合の設定

pd.concat()には、dfのリストまたは辞書を渡すことができます。

  • pd.concat([dfのリスト]) or
  • pd.concat({dfの辞書})

辞書で渡す場合には、次のように辞書のキーが新たなMutliindexとして追加されます。

df_concat = pd.concat({"Data1":df1, "Data2":df2})
df_concat
#           出身地   チーム
#       名前           
# Data1 田中  北海道  チームA  # <-Data1がインデックスとして追加された
#       佐藤   青森  チームB
#       鈴木   秋田  チームB
# Data2 後藤   青森  チームB# <-Data2がインデックスとして追加された
#       山田   宮城  チームC

辞書型でdfを結合する場合には、次の引数を追加で指定することができます。

設定内容 引数名
使用する要素の指定 keys=[使用するキーのリスト]
インデックス名の指定 names=[新たなインデックス列の名前]

keysで使用する要素を限定して、namesで追加されるMutiindex列に名前を付けてみましょう。

# 結合元辞書の準備
df_dict = {"Data1": df1, "Data2": df2, "Data3": df3}

# pd.concatで結合
pd.concat(df_dict, keys=["Data1", "Data2"], names=["ソース"])
#           出身地   チーム
# ソース   名前           
# Data1 田中  北海道  チームA
#       佐藤   青森  チームB
#       鈴木   秋田  チームB
# Data2 後藤   青森  チームB
#       山田   宮城  チームC

キーでデータソースを入力しておくと、結合後のdfにソースのインデックス列を追加できるので、結果がわかりやすくなりますね。

  • 【参考】Mulitiindexの基本操作は次の記事で紹介しています。
≫pandas Multiindex図解で解説|基本構造・変更・追加・解除・並べ替え
MultiindexのDataFrame, Seriesはデータの階層構造が視覚的にも把握しやすく、データの集計・分析が効率的に行えます。一方で、Multiindexでは次のような問題に直面することも…①普段使わないからMultiindexの中身がよくわからない②どうやっMultiindexを設定・解除するの?③インデックスを変更、入れ替え、ソートする方法は?この記事では、Multiindexの基本構造、設定・解除方法、変更・入れ替え・ソートについてわかりやすく図解付きで解説していきます。
www.yutaka-note.com/entry/pandas_multiind_set
 

merge|データ列をもとにした結合

.merge()は、基本的には2つのdfの特定の列を基準にして、2つのdfを結合します。

.merge()には、関数とメソッドがあり、それぞれ次のように使用します。

  • df1.merge(df2)
  • pd.merge(df1, df2)

どちらも挙動は同じですが、以下ではdf1df2を結合していることがわかりやすいメソッドを例に解説していきます。

次のサンプルデータで挙動を確認してみましょう。

# 結合先データ
df1 = pd.DataFrame({"Shop":["ShopA", "ShopA", "ShopB", "ShopB"],
                   "Item":["Apple", "Banana", "Apple", "Banana"]})
#      Shop    Item
# 0   ShopA   Apple
# 1   ShopA  Banana
# 2  ShopB   Apple
# 3  ShopB  Banana

# 統合データ
df2 = pd.DataFrame({"Item":["Apple", "Banana", "Carrot"],
                    "price":[100, 200, 300]})
#      Item  price
# 0   Apple    100
# 1  Banana    200
# 2  Carrot    300

df.merge()のデフォルト設定で、2つのdfを結合してみます。

df1.merge(df2)
#      Shop    Item  price
# 0   ShopA   Apple    100
# 1   ShopB   Apple    100
# 2   ShopA  Banana    200
# 3   ShopB  Banana    200

デフォルト設定では、df1df2の共通のカラム名の列を結合軸にして、dfが結合されます。

この例では、"Item"列が結合軸になって、df1に対してdf2"price"列が追加されるような形でデータが結合されています。

引数による結合方法の設定

主な設定変更用の引数は次の通りです。

結合先のdf1を左側(left)、結合するdf2を右側(right)と呼ぶことを覚えておくと、引数の意味がわかりやすくなります。

設定内容 引数名 適用
結合軸の設定 on="df1, df2の共通の列名" or
left_on="df1の列名" and
   right_on="df2の列名"
onで共通の列名を指定 or
left_on, right_onで個別に指定
インデックスを結合軸に設定 left_index=False or True,
right_index=False or True
・結合軸としてインデックス列を指定
・左側、右側の各dfonとの併用は不可
外部結合・内部結合の設定 how='inner', 'outer',
              'left','right',
              'cross'
'inner': 内部結合(デフォルト),
'outer':外部結合,
'left':左外部結合,
'right':右外部結合,
'cross':交差結合
同名列の接尾語 suffixes=('_x',' _y') df1df2に同じ列名があった場合に、
追加する接尾語

結合軸の設定方法|on

結合軸の設定方法としては、次の3パターンがあります。

  • デフォルト設定で結合軸を自動選択
    • 引数による指定なし:共通の列名の列が自動で結合軸になる
  • df1, df2で共通の列を指定する場合
    • on="列名"
  • df1, df2で異なる列名・インデックスを設定する場合
    • 左側 df1の指定: left_on = "列名" or left_index =True(インデックスを使用)
    • 右側 df2の指定: right_on = "列名" or right_index=True(インデックスを使用)

それぞれサンプルデータで挙動を確認してみます。

まずは次のデータで、デフォルト設定(指定なし)での挙動を確認します。

# 結合先データ
df1
#      Shop    Item
# 0   ShopA   Apple
# 1   ShopA  Banana
# 2   ShopB   Apple
# 3   ShopB  Banana

# 統合データ
df2
#      Item  price
# 0   Apple    100
# 1  Banana    200
# 2  Carrot    300

df1.merge(df2)
#      Shop    Item  price
# 0   ShopA   Apple    100
# 1   ShopB   Apple    100
# 2   ShopA  Banana    200
# 3   ShopB  Banana    200

列名が2つ以上共通の場合には、複数軸が結合軸になります。

df3 = pd.DataFrame({"Shop": ["ShopA", "ShopA", "ShopB"],
                    "Item":["Apple", "Banana", "Banana"],
                    "price":[150, 250, 350]})
#     Shop    Item  price
# 0  ShopA   Apple    150
# 1  ShopA  Banana    250
# 2  ShopB   Apple    350

df1.merge(df3)
#     Shop    Item  price
# 0  ShopA   Apple    150
# 1  ShopA  Banana    250
# 2  ShopB  Banana    350

この場合は、全ての結合時の値が同じデータのみが結合されるようになります。

上記の例では、"Shop", "Item"両方が一致していないとデータは結合されず、"ShopB", "Apple"の行は除外されました。

次にon="列名"で、df1, df2で共通の列を指定する例を見てみましょう。

df1.merge(df2, on="Item")
#      Shop    Item  price
# 0   ShopA   Apple    100
# 1   ShopB   Apple    100
# 2   ShopA  Banana    200
# 3   ShopB  Banana    200

次のようにリストで複数の列名を指定することも可能です。

df1.merge(df3, on=["Shop", "Item"])
#     Shop    Item  price
# 0  ShopA   Apple    150
# 1  ShopA  Banana    250
# 2  ShopB  Banana    350

この場合も、指定した全ての結合時の値が同じデータのみが結合されるようになります。

最後に、左側と右側で個別に列名またはインデックス指定をする例を確認します。

結合軸であった"Item"列をインデックス列に移動したdf4を用意し、挙動を確認してみます。

# データ列をインデックスに変換したdfの準備
df4 = df2.set_index("Item")
#         price
# Item         
# Apple     100
# Banana    200
# Carrot    300

# right_index=Trueでインデックスを結合軸に指定
df1.merge(df4, left_on="Item", right_index=True)

左右で個別に結合軸を設定できました。

これで結合軸の設定はOKですね。

  • 【参考】dfのインデックスの設定方法については、次の記事で解説しています。
    ≫pandas DataFrameにインデックス設定|パターン別にわかりやすく解説
    pandasのDataFrameでは、インデックス名でデータにアクセスします。しかし、DataFrameへのインデックス指定方法は少しわかりにくい部分も…。そこで、この記事では、パターン別に設定方法を解説!①DataFrame作成時にインデックス列指定、②既存DataFrameで指定、③ExcelやCSVから読み込み時に指定 ④インデックスの振り直し…
    www.yutaka-note.com/entry/pandas_index_setting
     

内部結合・外部結合の設定|how

内部結合、外部結合の設定はhowで行います。

設定内容 引数の設定内容 適用
内部結合 how="inner" 左右で共通のラベルのデータのみ結合(デフォルト)
外部結合 how="outer" 左右全てのデータを結合(欠損値はNaNになる)
左側外部結合 how="left" 左側にあるラベルのデータのみ結合
右側外部結合 how="right" 右側のにあるラベルのデータのみ結合
交差結合 how="cross" 左右の全組み合わせを生成するように結合

文章ではわかりにくい部分もあるので、各結合の違いを図解してみましょう。

図にしてみると、どこが結合軸として有効かよくわかりますね。

次のサンプルデータで挙動を確認してみます。

df5 = pd.DataFrame({"Item":["Apple", "Carrot"],
                    "price":[100, 300]})
#      Item  price
# 0   Apple    100
# 1  Carrot    300

df6 = pd.DataFrame({"Shop":["ShopA", "ShopA"],
                   "Item":["Apple", "Banana"]})
#     Shop    Item
# 0  ShopA   Apple
# 1  ShopA  Banana

df.merge()の結合方法の違いによる挙動の違いを確認してみましょう。

# 内部結合(how="inner", デフォルト)
df6.merge(df5) # or df6.merge(df5, how="outer")
#     Shop   Item  price
# 0  ShopA  Apple    100

# 外部結合(how="outer")
df6.merge(df5, how="outer")
#     Shop    Item  price
# 0  ShopA   Apple  100.0
# 1  ShopA  Banana    NaN
# 2    NaN  Carrot  300.0

# 左側外部結合(how="left")
df6.merge(df5, how="left")
#     Shop    Item  price
# 0  ShopA   Apple  100.0
# 1  ShopA  Banana    NaN

# # 右側外部結合(how="right")
df6.merge(df5, how="right")
#      Item  price
# 0   Apple    100
# 1  Carrot    300

# 交差結合(how="cross")
df6.merge(df5, how="cross")
#     Shop  Item_x  Item_y  price
# 0  ShopA   Apple   Apple    100
# 1  ShopA   Apple  Carrot    300
# 2  ShopA  Banana   Apple    100
# 3  ShopA  Banana  Carrot    300

同名列の接尾語|suffix

結合するにdf同じカラム名がある場合は、引数suffixに応じて接尾語が設定されます。

  • suffix=(_x,_y)
    • デフォルト:_x, _y

片方のみ接尾語を指定する場合は、指定しない方にFalseを指定します。

  • suffix=(None, df2の接尾語)
  • suffix=(df1の接尾語, None)

次のサンプルデータで挙動を確認してみます。

df5
#      Item  price
# 0   Apple    100
# 1  Carrot    300

df7 = pd.DataFrame({"Shop":["ShopA", "ShopA"],
                   "Item":["Apple", "Carrot"],
                   "price": [1000, 2000]})
#     Shop    Item  price
# 0  ShopA   Apple   1000
# 1  ShopA  Banana   2000

デフォルト設定と、片方のみ接尾語を設定する例を確認してみます。

# デフォルト設定
df5.merge(df7, on="Item")
#      Item  price_x   Shop  price_y
# 0   Apple      100  ShopA     1000
# 1  Carrot      300  ShopA     2000

# 右側のみ接尾語設定
df5.merge(df7, on="Item", suffixes=(None, "_New"))
#      Item  price   Shop  price_New
# 0   Apple    100  ShopA       1000
# 1  Carrot    300  ShopA       2000

join|インデックス列をもとにした結合

joinには次のような特徴があります。

  • df1に複数のdf2, df3,…を同時に結合可能
  • ただし、右側のdf2, df3,…の結合軸はインデックスのみ

個人的には、データベース的なdf1にどんどん補足データdf2, df3,…を追加していくときに便利です。

.merge()と同様に.join()もメソッドと関数があります。

  • df1.join(df2)
  • pd.join(df1, df2)
    • df2[df2, df3,…]のようなリストもOK

どちらも挙動は同じですが、以下ではdf1df2を結合していることがわかりやすいメソッドを例に解説していきます。

次のサンプルデータで挙動を確認してみましょう。

# 結合先データ
df1 = pd.DataFrame({"Shop":["ShopA", "ShopA", "ShopB", "ShopB"],
                   "Item":["Apple", "Banana", "Apple", "Banana"]}).set_index("Item")
#          Shop
# Item         
# Apple   ShopA
# Banana  ShopA
# Apple   ShopB
# Banana  ShopB

# 統合データ1
df2 = pd.DataFrame({"Item":["Apple", "Banana", "Carrot"],
                    "price":[100, 200, 300]}).set_index("Item")
#         price
# Item         
# Apple     100
# Banana    200
# Carrot    300

df3 = pd.DataFrame({"Item":["Apple", "Banana", "Carrot"],
                    "Color":["Red", "Yellow", "Orange"]}).set_index("Item")
#          Color
# Item          
# Apple      Red
# Banana  Yellow
# Carrot  Orange

df.join()のデフォルト設定で、2つのdfを結合してみます。

# 1つのdfを結合
df1.join(df2)
#          Shop  price
# Item                
# Apple   ShopA    100
# Apple   ShopB    100
# Banana  ShopA    200
# Banana  ShopB    200

# 複数のdfを結合
df1.join([df2, df3])
#          Shop  price   Color
# Item                        
# Apple   ShopA    100     Red
# Apple   ShopB    100     Red
# Banana  ShopA    200  Yellow
# Banana  ShopB    200  Yellow

デフォルト設定では、df1, df2, df3のインデックスを結合軸にして、dfが結合されます。

  • 【参考】joinを使う際は、インデックスの操作が重要です。次の記事も参考にしてみください。
≫pandas DataFrameにインデックス設定|パターン別にわかりやすく解説
pandasのDataFrameでは、インデックス名でデータにアクセスします。しかし、DataFrameへのインデックス指定方法は少しわかりにくい部分も…。そこで、この記事では、パターン別に設定方法を解説!①DataFrame作成時にインデックス列指定、②既存DataFrameで指定、③ExcelやCSVから読み込み時に指定 ④インデックスの振り直し…
www.yutaka-note.com/entry/pandas_index_setting
 
≫pandas インデックス列の基本操作|要素にアクセス、検索、欠損値処理
pandasのDataFrameでは、インデックス列の操作方法に関して、網羅的に解説!①インデックスの基本構造②インデックス内要素へのアクセス方法③インデックス内のデータ検索、並べ替え、重複処理、欠損値処理。サンプルコード付きでわかりやすく解説!
www.yutaka-note.com/entry/pandas_index_manip
 

引数による結合方法の設定

joinの主な設定変更用の引数は次の通りです。

設定内容 引数名 適用
左側df1の結合軸を
データ列に変更
on="df1の列名" 左側df1の結合軸を列に変更
※右側df2,df3…は変更不可(インデックスのみ)
外部・内部結合の設定 how='left',
            'right',
            'outer',
            'inner'
'left':左外部結合(デフォルト),
'right':右外部結合,
'inner': 内部結合,
"outer":外部結合
同名列の接尾語 lsuffix="左側の接尾語"
rsuffix="右側の接尾語"
df1df2に同じ列名があった場合に、
追加する接尾語

左側df1のみ結合軸を変更できたり、結合方法のデフォルトが左側外部結合だったりと、基本的な結合の基準が左側になっている点がjoinの特徴ですね。

データ列を結合軸に設定|on

joinは基本的にはインデックス列でデータを結合します。

ただし、引数やメソッドでデータ列を結合軸にすることも可能です。

結合元/結合先 特定の列を結合軸に設定する方法
左側df1 on="df1の列名"
右側df2,df3,… df2.set_index(列名)

左側df1は、引数onで結合軸にするデータ列を選択できます。

一方、右側df2の結合軸を変更する引数はないため、df2.set_index()で列をインデックスに変換します。

それぞれサンプルデータで挙動を確認してみます。

# 結合先データ
df4 = pd.DataFrame({"Shop":["ShopA", "ShopA", "ShopB", "ShopB"],
                   "Item":["Apple", "Banana", "Apple", "Banana"]})
#     Shop    Item # <- Itemを結合軸にする
# 0  ShopA   Apple
# 1  ShopA  Banana
# 2  ShopB   Apple
# 3  ShopB  Banana

# 統合データ1
df2
#         price
# Item         
# Apple     100
# Banana    200
# Carrot    300

# 左側dfの結合軸をonで指定
df4.join(df2, on="Item")
#     Shop    Item  price
# 0  ShopA   Apple    100
# 1  ShopA  Banana    200
# 2  ShopB   Apple    100
# 3  ShopB  Banana    200

次に右側dfで、df.set_index()を使用してデータ列を結合軸にする例を見てみます。

# 結合先データ
df1
#          Shop
# Item         
# Apple   ShopA
# Banana  ShopA
# Apple   ShopB
# Banana  ShopB

# 統合データ
df5 = pd.DataFrame({"Item":["Apple", "Banana", "Carrot"],
                    "price":[100, 200, 300]})
#      Item  price
# 0   Apple    100
# 1  Banana    200
# 2  Carrot    300

# 右側dfのデータ列をindexに設定後結合
df1.join(df5.set_index("Item"))
#          Shop  price
# Item                
# Apple   ShopA    100
# Apple   ShopB    100
# Banana  ShopA    200
# Banana  ShopB    200

内部結合・外部結合の設定|how

内部結合、外部結合の設定はhowで行います。

設定内容 引数の設定内容 適用
左側外部結合 how="left" 左側にあるラベルのデータのみ結合
右側外部結合 how="right" 右側のにあるラベルのデータのみ結合
外部結合 how="outer" 左右全てのデータを結合(欠損値はNaNになる)
内部結合 how="inner" 左右で共通のラベルのデータのみ結合(デフォルト)

こちらも、各結合の違いを図解してみましょう。

次のサンプルデータで挙動を確認してみます。

df6 = pd.DataFrame({"Shop":["ShopA", "ShopA"],
                   "Item":["Apple", "Banana"]}).set_index("Item")
#          Shop
# Item         
# Apple   ShopA
# Banana  ShopA

df7 = pd.DataFrame({"Item":["Apple", "Carrot"],
                    "price":[100, 300]}).set_index("Item")
#         price
# Item         
# Apple     100
# Carrot    300

df.join()の結合方法の違いによる挙動の違いを確認してみましょう。

# 左側外部結合(how="left", デフォルト)
df6.join(df7) # or df6.join(df5, how="left")
#          Shop  price
# Item                
# Apple   ShopA  100.0
# Banana  ShopA    NaN

# 右側外部結合(how="right")
df6.join(df7, how="right")
#          Shop  price
# Item                
# Apple   ShopA    100
# Carrot    NaN    300

# 外部結合(how="outer")
df6.join(df7, how="outer")
#          Shop  price
# Item                
# Apple   ShopA  100.0
# Banana  ShopA    NaN
# Carrot    NaN  300.0

# 内部結合(how="inner")
df6.join(df7, how="inner")
#         Shop  price
# Item               
# Apple  ShopA    100

同名列の接尾語|lssufix

結合するにdf同じカラム名がある場合、次のようなエラーが発生してしまいます。

df2.join(df8)

# ValueError: columns overlap but no suffix specified: Index(['price'], dtype='object')

この場合は、左右少なくともどちらかの接尾語を指定する必要があります。

  • lsuffix="df1の接尾語"
  • rsuffix="df2の接尾語"

次のサンプルデータで挙動を確認してみます。

df2
#         price
# Item         
# Apple     100
# Banana    200
# Carrot    300

df8 = pd.DataFrame({"Item":["Apple", "Carrot"],
                    "price": [1000, 2000]}).set_index("Item")
#         price
# Item         
# Apple    1000
# Carrot   2000

左側、右側でそれぞれ接尾語を設定した例を見てみましょう。

# 左側のdf1に接尾語設定
df2.join(df8, lsuffix="_old")
#         price_old   price
# Item                     
# Apple         100  1000.0
# Banana        200     NaN
# Carrot        300  2000.0

# 右側のdf2に接尾語設定
df2.join(df8, rsuffix="_new")
#         price  price_new
# Item                    
# Apple     100     1000.0
# Banana    200        NaN
# Carrot    300     2000.0

オススメ|pandasとデータ分析の勉強方法

今回はpandasのデータ連結・結合concat, merge, joinについて図解付きで解説しました。

pandasは便利すぎて操作方法がわかりにくいことがよくあります…。

結局はコツコツ学ぶのが、pandasマスターの近道ですよね!

≫【ブログカテゴリー:pandas】

データ分析初心者の方にはこちらの記事もおススメです。

私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。

何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。

≫独学でデータ分析を勉強するオススメ学習本
独学でのpythonデータ分析勉強に役立ったおススメ書籍を紹介していきます。業務でそれなりにデータ分析を行えるまで、いろいろな試行錯誤をしてきましたが、もし自分が今ゼロから勉強する立場ならどうするのがいいのか考えてみました。以下では、入門書、個別モジュール用、実践用の3つの視点でおススメ本を紹介していきます。
www.yutaka-note.com/entry/data_analysis
 

オススメのpandas本については、次の記事で紹介しています。

≫【レビュー】「Python実践データ分析100本ノック」|100本終えたらpandasが好きになっていた
Python実践データ分析100本ノックで、実際に100本終了したレビューです。pythonでのデータ分析の入門書としてかなりの良書だったと思います。・python2~3冊目に何を勉強しようか迷っている人・時間をかけずにデータ分析の基本を学びたい人・pandasへの抵抗を減らしたい人
www.yutaka-note.com/entry/nock_100
 
≫【レビュー】「Pythonによるデータ分析入門」| pandas開発者によるpandasユーザーのためのpandasの教科書!
「Pythonによるデータ分析入門」を、最初から最後まで実際に実践してみたレビューです。具体的にどのようなことができるようになったかを実例付きで紹介します!・DataFrameの生成方法・欠損値の処理方法・グラフ化の方法気になる学習時間は…?
www.yutaka-note.com/entry/2019/12/07/230219