web-dev-qa-db-de.com

Pandas Zusammenführen 101

  • Wie führe ich eine (LEFT | RIGHT | FULL) (INNER | OUTER) Verbindung mit Pandas durch?
  • Wie füge ich NaNs für fehlende Zeilen nach dem Zusammenführen hinzu?
  • Wie entferne ich NaNs nach dem Zusammenführen?
  • Kann ich auf dem Index zusammenführen?
  • Cross Join mit Pandas?
  • Wie füge ich mehrere DataFrames zusammen?
  • merge? join? concat? update? Wer? Was? Warum?!

... und mehr. Ich habe diese wiederkehrenden Fragen zu verschiedenen Aspekten der pandas Merge-Funktionalität gesehen. Die meisten Informationen zu Merge und seinen verschiedenen Anwendungsfällen sind heute auf Dutzende falsch formulierter, nicht durchsuchbarer Posts verteilt. Ziel ist es, einige der wichtigsten Punkte für die Nachwelt zusammenzufassen.

Diese QnA ist als nächster Teil einer Reihe hilfreicher Benutzerhandbücher zu allgemeinen pandas Redewendungen gedacht (siehe dieser Beitrag zum Pivoting und dieser Beitrag zur Verkettung) , worauf ich später noch eingehen werde).

Bitte beachte, dass dieser Beitrag nicht ​​als Ersatz für Dokumentation gedacht ist, also lies das bitte auch! Einige der Beispiele stammen von dort.

225
cs95

Dieser Beitrag zielt darauf ab, den Lesern eine Einführung in das Zusammenführen mit Pandas zu geben, wie man es benutzt und wann man es nicht benutzt.

Im Einzelnen wird dieser Beitrag wie folgt behandelt:

  • Die Grundlagen - Arten von Verknüpfungen (LINKS, RECHTS, AUSSEN, INNEN)

    • zusammenführen mit verschiedenen Spaltennamen
    • vermeidung doppelter Zusammenführungsschlüsselspalten in der Ausgabe
  • Zusammenführen mit Index unter verschiedenen Bedingungen
    • effektiv mit Ihrem benannten Index
    • schlüssel als Index einer und Spalte einer anderen zusammenführen
  • Multiway-Zusammenführungen für Spalten und Indizes (eindeutig und nicht eindeutig)
  • Bemerkenswerte Alternativen zu merge und join

Was dieser Beitrag nicht durchlaufen wird:

  • Performancebezogene Diskussionen und Timings (vorerst). Meist bemerkenswerte Erwähnungen von besseren Alternativen, wo immer dies angebracht ist.
  • Behandeln von Suffixen, Entfernen zusätzlicher Spalten, Umbenennen von Ausgaben und anderer spezifischer Anwendungsfälle. Es gibt andere (lies: bessere) Posts, die sich damit befassen, also finde es heraus!

Hinweis
Die meisten Beispiele verwenden standardmäßig INNER JOIN-Vorgänge, während verschiedene Funktionen demonstriert werden, sofern nicht anders angegeben.

Außerdem können hier alle DataFrames kopiert und repliziert werden, damit Sie damit spielen können. Lesen Sie auch dieser Beitrag , wie Sie DataFrames aus Ihrer Zwischenablage lesen.

Zuletzt wurden alle visuellen Darstellungen von JOIN-Vorgängen mit Google Drawings von Hand gezeichnet. Inspiration von hier .

Genug geredet, zeig mir einfach, wie man merge benutzt!

Setup

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

Der Einfachheit halber trägt die Schlüsselspalte (vorerst) den gleichen Namen.

Ein INNER JOIN wird dargestellt durch

Hinweis
Zusammen mit den kommenden Zahlen folgen alle dieser Konvention:

  • Blau zeigt Zeilen an, die im Zusammenführungsergebnis vorhanden sind
  • rot kennzeichnet Zeilen, die vom Ergebnis ausgeschlossen (d. h. entfernt) sind
  • grün zeigt fehlende Werte an, die im Ergebnis durch NaNs ersetzt werden

Rufen Sie pd.merge auf, um einen INNER JOIN auszuführen, und geben Sie den linken DataFrame, den rechten DataFrame und den Verknüpfungsschlüssel an.

pd.merge(left, right, on='key')

  key   value_x   value_y
0   B  0.400157  1.867558
1   D  2.240893 -0.977278

Dies gibt nur Zeilen von left und right zurück, die einen gemeinsamen Schlüssel haben (in diesem Beispiel "B" und "D").

In neueren Versionen von pandas (v0.21 oder so) ist merge jetzt eine Funktion erster Ordnung, sodass Sie DataFrame.merge aufrufen können.

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

Ein LEFT OUTER JOIN oder LEFT JOIN wird durch dargestellt

Dies kann durch Angabe von how='left' erfolgen.

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

Beachten Sie hier die Platzierung der NaNs. Wenn Sie how='left' angeben, werden nur Schlüssel aus left verwendet und fehlende Daten aus right werden durch NaN ersetzt.

Und in ähnlicher Weise für einen RIGHT OUTER JOIN oder RIGHT JOIN der ist ...

... how='right' angeben:

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

Hier werden Schlüssel aus right verwendet, und fehlende Daten aus left werden durch NaN ersetzt.

Schließlich für die FULL OUTER JOIN , gegeben durch

gib how='outer' an.

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

Dies verwendet die Schlüssel aus beiden Frames und NaNs werden für fehlende Zeilen in beiden eingefügt.

Die Dokumentation fasst diese verschiedenen Zusammenführungen gut zusammen:

enter image description here

Andere JOINs - LEFT-Excluding, RIGHT-Excluding und FULL-Excluding/ANTI JOINs

Wenn Sie LINKS-ausschließende JOINs und RECHTS-ausschließende JOINs in zwei benötigen Schritte.

Für LEFT-Excluding JOIN, dargestellt als

Führen Sie zunächst einen LEFT OUTER JOIN durch und filtern Sie dann (ohne!) Zeilen, die nur aus left stammen.

(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

Wo,

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

Und in ähnlicher Weise, für einen RECHTS-ausschließenden JOIN,

(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

Zuletzt, wenn Sie eine Zusammenführung durchführen müssen, bei der nur die Schlüssel von links oder rechts beibehalten werden, aber nicht beide (IOW, Ausführen eines ANTI-JOIN ) ,

Sie können dies auf ähnliche Weise tun -

(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

Unterschiedliche Namen für Schlüsselspalten

Wenn die Schlüsselspalten unterschiedlich benannt sind, z. B. left hat keyLeft und right hat keyRight anstelle von key, müssen Sie left_on angeben. und right_on als Argumente anstelle von 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

Vermeidung doppelter Schlüsselspalten in der Ausgabe

Beim Zusammenführen von keyLeft von left und keyRight von right, wenn Sie nur eines der keyLeft oder keyRight (aber nicht beide) möchten In der Ausgabe können Sie als ersten Schritt den Index festlegen.

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

Vergleichen Sie dies mit der Ausgabe des Befehls kurz vor (d. H. Der Ausgabe von left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')), und Sie werden feststellen, dass keyLeft fehlt. Sie können herausfinden, welche Spalte basierend auf dem Index des Frames als Schlüssel beibehalten werden soll. Dies kann beispielsweise dann von Bedeutung sein, wenn eine OUTER JOIN-Operation ausgeführt wird.

Nur eine einzelne Spalte aus einer der DataFrames zusammenführen

Zum Beispiel betrachten

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

Wenn Sie nur "new_val" (ohne eine der anderen Spalten) zusammenführen müssen, können Sie vor dem Zusammenführen in der Regel nur einige Spalten auswählen:

left.merge(right3[['key', 'newcol']], on='key')

  key     value  newcol
0   B  0.400157       0
1   D  2.240893       1

Wenn Sie einen LEFT OUTER JOIN durchführen, würde eine performantere Lösung map beinhalten:

# 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

Wie bereits erwähnt, ist dies ähnlich, aber schneller als

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

Zusammenführen in mehreren Spalten

Um an mehr als einer Spalte teilzunehmen, geben Sie eine Liste für on an (oder left_on und right_on entsprechend).

left.merge(right, on=['key1', 'key2'] ...)

Oder, falls die Namen unterschiedlich sind,

left.merge(right, left_on=['lkey1', 'lkey2'], right_on=['rkey1', 'rkey2'])

Andere nützliche merge* Operationen und Funktionen

In diesem Abschnitt werden nur die Grundlagen behandelt. Er soll nur Ihren Appetit anregen. Weitere Beispiele und Fälle finden Sie in der Dokumentation zu merge, join und concat sowie in den Links zu den Funktionsspezifikationen.


Indexbasiertes * -JOIN (+ Indexspalte merges)

Setup

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

In der Regel sieht eine Zusammenführung im Index folgendermaßen aus:

left.merge(right, left_index=True, right_index=True)


         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Unterstützung für Indexnamen

Wenn Ihr Index benannt ist, können Benutzer der Version 0.23 den Ebenennamen auch mit on (oder left_on und right_on nach Bedarf) angeben.

left.merge(right, on='idxkey')

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Zusammenführen auf Index einer, Spalte (n) einer anderen

Es ist möglich (und ziemlich einfach), den Index eines und die Spalte eines anderen zu verwenden, um eine Zusammenführung durchzuführen. Zum Beispiel,

left.merge(right, left_on='key1', right_index=True)

Oder umgekehrt (right_on=... und 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

In diesem speziellen Fall wird der Index für left benannt, sodass Sie den Indexnamen auch mit left_on verwenden können.

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
Neben diesen gibt es eine weitere prägnante Option. Sie können DataFrame.join verwenden, der standardmäßig Verknüpfungen im Index erstellt. DataFrame.join führt standardmäßig einen LEFT OUTER JOIN durch, daher ist hier how='inner' erforderlich.

left.join(right, how='inner', lsuffix='_x', rsuffix='_y')

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Beachten Sie, dass ich die Argumente lsuffix und rsuffix angeben musste, da join andernfalls einen Fehler verursachen würde:

left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')

Da die Spaltennamen gleich sind. Dies wäre kein Problem, wenn sie anders benannt wären.

left.rename(columns={'value':'leftvalue'}).join(right, how='inner')

        leftvalue     value
idxkey                     
B       -0.402655  0.543843
D       -0.524349  0.013135

pd.concat
Als Alternative für indexbasierte Joins können Sie auch pd.concat verwenden:

pd.concat([left, right], axis=1, sort=False, join='inner')

           value     value
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Lassen Sie join='inner' weg, wenn Sie einen FULL OUTER JOIN benötigen (Standardeinstellung):

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

Weitere Informationen finden Sie unter dieser kanonische Beitrag zu pd.concat von @piRSquared .


Verallgemeinern: merge mehrere DataFrames

In vielen Fällen tritt die Situation auf, wenn mehrere DataFrames zusammengeführt werden sollen. Naiv kann dies durch Verketten von merge Aufrufen erfolgen:

df1.merge(df2, ...).merge(df3, ...)

Dies gerät jedoch bei vielen DataFrames schnell außer Kontrolle. Darüber hinaus kann es erforderlich sein, für eine unbekannte Anzahl von DataFrames eine Verallgemeinerung vorzunehmen.

Hier stelle ich pd.concat für Mehrfachverknüpfungen mit eindeutigen Schlüsseln und DataFrame.join für Mehrfachverknüpfungen mit nicht eindeutigen Schlüsseln vor. Zunächst das Setup.

# 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]

Multiway-Zusammenführung für eindeutige Schlüssel (oder Index)

Wenn Ihre Schlüssel (hier kann es sich entweder um eine Spalte oder einen Index handeln) eindeutig sind, können Sie pd.concat verwenden. Beachten Sie, dass pd.concat DataFrames im Index verbindet .

# 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

Lassen Sie join='inner' weg, um eine vollständige äußere Verknüpfung zu erhalten. Beachten Sie, dass Sie keine LEFT- oder RIGHT-OUTER-Joins angeben können (wenn Sie diese benötigen, verwenden Sie join, wie unten beschrieben).

Multiway-Zusammenführung bei Schlüsseln mit Duplikaten

concat ist schnell, hat aber seine Mängel. Duplikate können nicht verarbeitet werden.

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)

In dieser Situation können wir join verwenden, da es nicht eindeutige Schlüssel verarbeiten kann (beachten Sie, dass join DataFrames in ihrem Index verbindet; es ruft merge unter der Haube auf und führt einen LEFT OUTER JOIN aus Falls nicht anders angegeben).

# 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
299
cs95

Eine zusätzliche visuelle Ansicht von pd.concat([df0, df1], kwargs). Beachten Sie, dass die Bedeutung von kwarg axis=0 oder axis=1 nicht so intuitiv ist wie die von df.mean() oder df.apply(func)

on pd.concat([df0, df1])

17
eliu