この投稿は、パンダとのSQL風味のマージ、その使用方法、および使用しない場合の入門書を読者に提供することを目的としています。
特に、この投稿の内容は次のとおりです。
この投稿が通過しないこと:
- パフォーマンス関連のディスカッションとタイミング(現時点では)。適切な場合は常に、より優れた代替案についての最も注目すべき言及。
- サフィックスの処理、余分な列の削除、出力の名前変更、およびその他の特定の使用例。これに対処する他の(読む:より良い)投稿があるので、それを理解してください!
注
特に指定のない限り、ほとんどの例では、さまざまな機能を示しながら、デフォルトでINNER JOIN操作が行われます。
さらに、ここにあるすべてのデータフレームをコピーして複製できるため、それらを使って遊ぶことができます。また、
クリップボードからDataFrameを読み取る方法については、この投稿を参照してください。
最後に、JOIN操作のすべての視覚的表現は、Google図形描画を使用して手書きされています。ここからのインスピレーション。
十分な話、使い方を教えてくださいmerge
!
セットアップ
np.random.seed(0)
left = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)})
right = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value': np.random.randn(4)})
left
key value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right
key value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
簡単にするために、キーカラムは同じ名前です(今のところ)。
アンINNER JOINはで表され、
なお、
今後の数値はすべて、この規則に従うとともに、これを:
- 青は、マージ結果に存在する行を示します
- 赤は、結果から除外された(つまり、削除された)行を示します
- 緑は、結果でNaNに置き換えられる欠損値を示します
INNER JOINを実行するmerge
には、左側のDataFrameを呼び出し、右側のDataFrameと結合キー(少なくとも)を引数として指定します。
left.merge(right, on='key')
# Or, if you want to be explicit
# left.merge(right, on='key', how='inner')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
この戻り行のみからleft
とright
共有する共通鍵(この例では、「B」および「D)。
A LEFT OUTER JOIN、またはLEFT JOINは、がで表され
これは、を指定することで実行できますhow='left'
。
left.merge(right, on='key', how='left')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
ここでNaNの配置に注意してください。を指定するとhow='left'
、からのキーのみleft
が使用され、からの欠落データright
はNaNに置き換えられます。
同様に、RIGHT OUTER JOINまたはRIGHT JOINの場合...
...具体的にhow='right'
:
left.merge(right, on='key', how='right')
key value_x value_y
0 B 0.400157 1.867558
1 D 2.240893 -0.977278
2 E NaN 0.950088
3 F NaN -0.151357
ここでは、からのキーright
が使用され、からの欠落データleft
はNaNに置き換えられます。
最後に、以下によって与えられるFULL OUTER JOINについて、
を指定しますhow='outer'
。
left.merge(right, on='key', how='outer')
key value_x value_y
0 A 1.764052 NaN
1 B 0.400157 1.867558
2 C 0.978738 NaN
3 D 2.240893 -0.977278
4 E NaN 0.950088
5 F NaN -0.151357
これは両方のフレームのキーを使用し、NaNは両方の欠落行に挿入されます。
ドキュメントはこれらの様々なマージをうまくまとめています:
その他の結合-左除外、右除外、および完全除外/ ANTI結合
2つの手順でLEFT除外JOINとRIGHT 除外JOINが必要な場合。
左除外結合の場合、次のように表されます
LEFT OUTER JOINを実行してからleft
、次の行のみをフィルタリング(除外!)します。
(left.merge(right, on='key', how='left', indicator=True)
.query('_merge == "left_only"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
どこ、
left.merge(right, on='key', how='left', indicator=True)
key value_x value_y _merge
0 A 1.764052 NaN left_only
1 B 0.400157 1.867558 both
2 C 0.978738 NaN left_only
3 D 2.240893 -0.977278 both
同様に、右除外結合の場合、
(left.merge(right, on='key', how='right', indicator=True)
.query('_merge == "right_only"')
.drop('_merge', 1))
key value_x value_y
2 E NaN 0.950088
3 F NaN -0.151357
最後に、左または右からのキーのみを保持し、両方は保持しないマージを実行する必要がある場合(IOW、ANTI-JOINの実行)、
同様の方法でこれを行うことができます—
(left.merge(right, on='key', how='outer', indicator=True)
.query('_merge != "both"')
.drop('_merge', 1))
key value_x value_y
0 A 1.764052 NaN
2 C 0.978738 NaN
4 E NaN 0.950088
5 F NaN -0.151357
キー列の異なる名前
キー列の名前が異なる場合(たとえば、left
has keyLeft
とright
hasのkeyRight
代わりに)は、次の代わりにおよびを引数としてkey
指定する必要がleft_on
あります。right_on
on
left2 = left.rename({'key':'keyLeft'}, axis=1)
right2 = right.rename({'key':'keyRight'}, axis=1)
left2
keyLeft value
0 A 1.764052
1 B 0.400157
2 C 0.978738
3 D 2.240893
right2
keyRight value
0 B 1.867558
1 D -0.977278
2 E 0.950088
3 F -0.151357
left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
keyLeft value_x keyRight value_y
0 B 0.400157 B 1.867558
1 D 2.240893 D -0.977278
出力でのキー列の重複を回避する
keyLeft
from left
とkeyRight
fromをマージするときに、出力にまたはのright
いずれかのみ(両方ではない)が必要な場合は、最初のステップとしてインデックスを設定することから始めます。keyLeft
keyRight
left3 = left2.set_index('keyLeft')
left3.merge(right2, left_index=True, right_on='keyRight')
value_x keyRight value_y
0 0.400157 B 1.867558
1 2.240893 D -0.977278
これを直前のコマンドの出力(つまり、の出力left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')
)と比較すると、欠落していることがわかりますkeyLeft
。どのフレームのインデックスがキーとして設定されているかに基づいて、保持する列を特定できます。これは、たとえば、いくつかのOUTER JOIN操作を実行するときに問題になる場合があります。
のいずれかから単一の列のみをマージする DataFrames
たとえば、
right3 = right.assign(newcol=np.arange(len(right)))
right3
key value newcol
0 B 1.867558 0
1 D -0.977278 1
2 E 0.950088 2
3 F -0.151357 3
「new_val」のみをマージする必要がある場合(他の列はなし)、通常はマージする前に列をサブセット化できます。
left.merge(right3[['key', 'newcol']], on='key')
key value newcol
0 B 0.400157 0
1 D 2.240893 1
LEFT OUTER JOINを実行している場合、よりパフォーマンスの高いソリューションには以下が含まれmap
ます。
# left['newcol'] = left['key'].map(right3.set_index('key')['newcol']))
left.assign(newcol=left['key'].map(right3.set_index('key')['newcol']))
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
前述のように、これは似ていますが、
left.merge(right3[['key', 'newcol']], on='key', how='left')
key value newcol
0 A 1.764052 NaN
1 B 0.400157 0.0
2 C 0.978738 NaN
3 D 2.240893 1.0
複数の列でのマージ
複数の列を結合するには、リストon
(またはleft_on
、right_on
必要に応じてand )を指定します。
left.merge(right, on=['key1', 'key2'] ...)
または、名前が異なる場合は、
left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])
その他の便利なmerge*
操作と機能
このセクションでは、ごく基本的な内容のみを取り上げ、食欲を刺激することのみを目的としています。より多くの例と例については、参照のドキュメントをmerge
、join
とconcat
だけでなく、機能仕様へのリンク。
インデックスベースの* -JOIN(+ index-column merge
s)
セットアップ
np.random.seed([3, 14])
left = pd.DataFrame({'value': np.random.randn(4)}, index=['A', 'B', 'C', 'D'])
right = pd.DataFrame({'value': np.random.randn(4)}, index=['B', 'D', 'E', 'F'])
left.index.name = right.index.name = 'idxkey'
left
value
idxkey
A -0.602923
B -0.402655
C 0.302329
D -0.524349
right
value
idxkey
B 0.543843
D 0.013135
E -0.326498
F 1.385076
通常、インデックスのマージは次のようになります。
left.merge(right, left_index=True, right_index=True)
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
インデックス名のサポート
あなたのインデックスが命名されている場合は、v0.23ユーザーもにレベル名を指定することができますon
(またはleft_on
およびright_on
必要に応じて)。
left.merge(right, on='idxkey')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
1つのインデックス、別の列のマージ
マージを実行するために、1つのインデックスと別のインデックスを使用することができます(非常に簡単です)。例えば、
left.merge(right, left_on='key1', right_index=True)
またはその逆(right_on=...
およびleft_index=True
)。
right2 = right.reset_index().rename({'idxkey' : 'colkey'}, axis=1)
right2
colkey value
0 B 0.543843
1 D 0.013135
2 E -0.326498
3 F 1.385076
left.merge(right2, left_index=True, right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
この特別なケースでは、のインデックスにleft
名前が付けられているためleft_on
、次のようにでインデックス名を使用できます。
left.merge(right2, left_on='idxkey', right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
DataFrame.join
これらに加えて、別の簡潔なオプションがあります。DataFrame.join
インデックスで結合するデフォルトを使用できます。DataFrame.join
デフォルトではLEFT OUTER JOINを実行するため、ここhow='inner'
で必要です。
left.join(right, how='inner', lsuffix='_x', rsuffix='_y')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
lsuffix
とrsuffix
引数を指定する必要があることに注意してください。join
そうしないとエラーになります。
left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')
列名は同じなので。名前が異なる場合、これは問題にはなりません。
left.rename(columns={'value':'leftvalue'}).join(right, how='inner')
leftvalue value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
pd.concat
最後に、インデックスベースの結合の代替として、次を使用できますpd.concat
。
pd.concat([left, right], axis=1, sort=False, join='inner')
value value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
join='inner'
FULL OUTER JOIN(デフォルト)が必要な場合は省略します。
pd.concat([left, right], axis=1, sort=False)
value value
A -0.602923 NaN
B -0.402655 0.543843
C 0.302329 NaN
D -0.524349 0.013135
E NaN -0.326498
F NaN 1.385076
詳細についてはpd.concat
、@ piRSquaredによるこの正規の投稿を参照してください。
一般化:merge
複数のデータフレームを使用する
多くの場合、状況は複数のデータフレームが一緒にマージされるときに発生します。簡単に言えば、これはmerge
呼び出しを連鎖させることによって行うことができます:
df1.merge(df2, ...).merge(df3, ...)
ただし、これは多くのデータフレームではすぐに手に負えなくなります。さらに、不明な数のデータフレームを一般化する必要がある場合があります。
ここで私は紹介pd.concat
マルチウェイは、上の加入のためのユニークなキー、およびDataFrame.join
マルチウェイのために参加する非ユニークキー。まず、セットアップ。
# Setup.
np.random.seed(0)
A = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'valueA': np.random.randn(4)})
B = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'valueB': np.random.randn(4)})
C = pd.DataFrame({'key': ['D', 'E', 'J', 'C'], 'valueC': np.ones(4)})
dfs = [A, B, C]
# Note, the "key" column values are unique, so the index is unique.
A2 = A.set_index('key')
B2 = B.set_index('key')
C2 = C.set_index('key')
dfs2 = [A2, B2, C2]
一意のキー(またはインデックス)での多方向マージ
キー(ここでは、キーは列またはインデックスのいずれか)が一意である場合は、を使用できますpd.concat
。pd.concat
は、インデックスでDataFrameを結合します。
# merge on `key` column, you'll need to set the index before concatenating
pd.concat([
df.set_index('key') for df in dfs], axis=1, join='inner'
).reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# merge on `key` index
pd.concat(dfs2, axis=1, sort=False, join='inner')
valueA valueB valueC
key
D 2.240893 -0.977278 1.0
join='inner'
FULL OUTER JOINは省略します。LEFTまたはRIGHT OUTER結合は指定できないことに注意してください(これらが必要な場合はjoin
、以下で説明するを使用してください)。
重複のあるキーの多方向マージ
concat
高速ですが、欠点があります。重複は処理できません。
A3 = pd.DataFrame({'key': ['A', 'B', 'C', 'D', 'D'], 'valueA': np.random.randn(5)})
pd.concat([df.set_index('key') for df in [A3, B, C]], axis=1, join='inner')
ValueError: Shape of passed values is (3, 4), indices imply (3, 2)
この状況では、join
一意ではないキーを処理できるため、これを使用できます(join
インデックスでDataFrame を結合します。merge
特に指定のない限り、内部で呼び出し、LEFT OUTER JOINを実行します)。
# join on `key` column, set as the index first
# For inner join. For left join, omit the "how" argument.
A.set_index('key').join(
[df.set_index('key') for df in (B, C)], how='inner').reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# join on `key` index
A3.set_index('key').join([B2, C2], how='inner')
valueA valueB valueC
key
D 1.454274 -0.977278 1.0
D 0.761038 -0.977278 1.0