Was ist der Unterschied zwischen Beitreten und Zusammenführen in Pandas?

208

Angenommen, ich habe zwei DataFrames wie folgt:

left = pd.DataFrame({'key1': ['foo', 'bar'], 'lval': [1, 2]})

right = pd.DataFrame({'key2': ['foo', 'bar'], 'rval': [4, 5]})

Ich möchte sie zusammenführen, also versuche ich so etwas:

pd.merge(left, right, left_on='key1', right_on='key2')

Und ich bin glücklich

    key1    lval    key2    rval
0   foo     1       foo     4
1   bar     2       bar     5

Aber ich versuche, die Join-Methode zu verwenden, von der ich angenommen habe, dass sie ziemlich ähnlich ist.

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

Und ich verstehe das:

//anaconda/lib/python2.7/site-packages/pandas/tools/merge.pyc in _validate_specification(self)
    406             if self.right_index:
    407                 if not ((len(self.left_on) == self.right.index.nlevels)):
--> 408                     raise AssertionError()
    409                 self.right_on = [None] * n
    410         elif self.right_on is not None:

AssertionError: 

Was vermisse ich?

munk
quelle
4
Das spezifische Problem hierbei ist, dass mergeSpalten von leftmit Spalten von verbunden werden right, was Sie möchten, aber join(... on=[...])Spalten von leftmit Indexschlüsseln von verknüpfen right, was nicht das ist, was Sie möchten. Siehe meine Antwort unten für weitere Details.
Matthias Fripp
3
DataFrame.join () möchte immer die Indizes oder Schlüssel des Anrufers (durch onOption angegeben) mit den otherIndizes des Anrufers abgleichen . Denken Sie daran, Indizes für die Verknüpfung. Während merge () eine allgemeinere Methode ist.
Jiapeng Zhang

Antworten:

87

Ich benutze immer joinauf Indizes:

import pandas as pd
left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]}).set_index('key')
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]}).set_index('key')
left.join(right, lsuffix='_l', rsuffix='_r')

     val_l  val_r
key            
foo      1      4
bar      2      5

Dieselbe Funktionalität kann durch Verwendung mergeder folgenden Spalten erreicht werden:

left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]})
left.merge(right, on=('key'), suffixes=('_l', '_r'))

   key  val_l  val_r
0  foo      1      4
1  bar      2      5
Paul H.
quelle
Der Fehler scheint zu sagen, dass erwartet wird, dass der Multi-Index rightdieselbe Tiefe wie die Länge hat on. Das macht für mich irgendwie Sinn. Ich kann akzeptieren, dass die Semantik anders ist. Aber ich würde gerne wissen, ob ich das gleiche Verhalten mit df.join
munk
344

pandas.merge() ist die zugrunde liegende Funktion, die für das gesamte Zusammenführungs- / Verknüpfungsverhalten verwendet wird.

DataFrames bieten die Methoden pandas.DataFrame.merge()und pandas.DataFrame.join()als bequeme Möglichkeit, auf die Funktionen von zuzugreifen pandas.merge(). Zum Beispiel df1.merge(right=df2, ...)ist äquivalent zupandas.merge(left=df1, right=df2, ...) .

Dies sind die Hauptunterschiede zwischen df.join()und df.merge():

  1. Suche in der rechten Tabelle: Verbindet df1.join(df2)immer über den Index von df2, df1.merge(df2)kann jedoch mit einer oder mehreren Spalten von df2(Standard) oder mit dem Index von df2(mit right_index=True) verknüpft werden.
  2. Suche in der linken Tabelle: df1.join(df2)Verwendet standardmäßig den Index von df1und df1.merge(df2)verwendet die Spalte (n) von df1. Dies kann durch Angabe von df1.join(df2, on=key_or_keys)oder überschrieben werden df1.merge(df2, left_index=True).
  3. Left vs Inner Join: df1.join(df2)Führt standardmäßig einen Left Join durch (behält alle Zeilen von bei df1), führt jedoch df.mergestandardmäßig einen Inner Join durch (gibt nur übereinstimmende Zeilen von df1und zurück df2).

Der generische Ansatz ist also, pandas.merge(df1, df2)oder zu verwenden df1.merge(df2). In einigen häufigen Situationen (Beibehalten aller Zeilen df1und Verknüpfen mit einem Index df2) können Sie jedoch einige Eingaben speichern, indem Sie df1.join(df2)stattdessen verwenden.

Einige Hinweise zu diesen Problemen aus der Dokumentation unter http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging :

merge ist eine Funktion im Pandas-Namespace und auch als DataFrame-Instanzmethode verfügbar, wobei der aufrufende DataFrame implizit als linkes Objekt im Join betrachtet wird.

Die zugehörige DataFrame.joinMethode wird mergeintern für die Index-on-Index- und Index-on-Column-Verknüpfungen verwendet, verbindet sich jedoch standardmäßig mit Indizes, anstatt zu versuchen, gemeinsame Spalten zu verknüpfen (das Standardverhalten für merge). Wenn Sie sich dem Index anschließen, möchten Sie sich möglicherweise DataFrame.joinetwas Tipparbeit ersparen.

...

Diese beiden Funktionsaufrufe sind völlig gleichwertig:

left.join(right, on=key_or_keys)
pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)
Matthias Fripp
quelle
17
Dies sollte definitiv die akzeptierte Antwort sein! Vielen Dank für die gründliche Erklärung
Yohan Obadia
@Matthias Fripp, Vielleicht ist es für erfahrene Leute selbstverständlich, aber man könnte auch sagen, dass "Nachschlagen in der rechten Tabelle: df1.join (df2) kann zu df1.join (df2, on = key_or_keys?
spacedustpi
@spacedustpi, ich denke du sagst, dass du damit on=key_or_keysdie Art und Weise ändern kannst , wie Zeilen in der richtigen Tabelle gefunden werden. Dies ist jedoch nicht der Fall. Das onArgument ändert die Suche in der linken Tabelle ( df1) von Index zu Spalte (n). Selbst mit diesem Argument wird die richtige Tabelle ( df2) über ihren Index abgeglichen. (Siehe das letzte Beispiel oben.)
Matthias Fripp
Pandas hat verschiedene Methoden, um mit diesen Situationen umzugehen, darunter Zusammenführen, Verbinden, Anhängen, Konzentrieren, Kombinieren, Kombinieren. Schauen Sie sich diese an, um einen Eindruck davon zu bekommen, welche für Ihre Situation am besten geeignet ist
Xiaxio
13

Ich glaube, das join()ist nur eine bequeme Methode. Versuchen Sie df1.merge(df2)stattdessen, die Ihnen erlaubt , zu spezifizieren left_onund right_on:

In [30]: left.merge(right, left_on="key1", right_on="key2")
Out[30]: 
  key1  lval key2  rval
0  foo     1  foo     4
1  bar     2  bar     5
Noah
quelle
11

Aus dieser Dokumentation

pandas bietet eine einzige Funktion, Merge, als Einstiegspunkt für alle Standard-Datenbankverbindungsvorgänge zwischen DataFrame-Objekten:

merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)

Und :

DataFrame.joinist eine bequeme Methode zum Kombinieren der Spalten von zwei möglicherweise unterschiedlich indizierten DataFrames zu einem einzigen Ergebnis-DataFrame. Hier ist ein sehr einfaches Beispiel: Die Datenausrichtung erfolgt hier auf den Indizes (Zeilenbeschriftungen). Das gleiche Verhalten kann durch Zusammenführen und zusätzliche Argumente erreicht werden, die es anweisen, die Indizes zu verwenden:

result = pd.merge(left, right, left_index=True, right_index=True,
how='outer')
Romain Jouin
quelle
8

Einer der Unterschiede besteht darin, mergedass ein neuer Index erstellt wird und joinder Index auf der linken Seite beibehalten wird. Es kann eine große Konsequenz für Ihre späteren Transformationen haben, wenn Sie fälschlicherweise annehmen, dass Ihr Index mit nicht geändert wird merge.

Beispielsweise:

import pandas as pd

df1 = pd.DataFrame({'org_index': [101, 102, 103, 104],
                    'date': [201801, 201801, 201802, 201802],
                    'val': [1, 2, 3, 4]}, index=[101, 102, 103, 104])
df1

       date  org_index  val
101  201801        101    1
102  201801        102    2
103  201802        103    3
104  201802        104    4

- -

df2 = pd.DataFrame({'date': [201801, 201802], 'dateval': ['A', 'B']}).set_index('date')
df2

       dateval
date          
201801       A
201802       B

- -

df1.merge(df2, on='date')

     date  org_index  val dateval
0  201801        101    1       A
1  201801        102    2       A
2  201802        103    3       B
3  201802        104    4       B

- -

df1.join(df2, on='date')
       date  org_index  val dateval
101  201801        101    1       A
102  201801        102    2       A
103  201802        103    3       B
104  201802        104    4       B
steco
quelle
Das ist richtig. Wenn wir die beiden Datenrahmen in anderen Spalten als Indizes zusammenführen, erhalten wir einen neuen Index. Wenn wir jedoch die Indizes beider Datenrahmen zusammenführen, erhalten wir einen Datenrahmen mit demselben Index. Um nach dem Zusammenführen denselben Index zu erhalten, können wir die Spalten zu unserem Index (für den wir zusammenführen möchten) für beide Datenrahmen machen und dann die Datenrahmen mit dem neu erstellten Index zusammenführen.
Hasan Najeeb
Sehr aufschlussreich. Ich habe die Indizierung nie benötigt (normalerweise habe ich den Index nur zurückgesetzt), aber dies kann in einigen Fällen einen großen Unterschied machen.
Irene
4
  • Join: Standardindex (Wenn derselbe Spaltenname verwendet wird, wird im Standardmodus ein Fehler ausgegeben, da Sie weder lsuffix noch rsuffix definiert haben.)
df_1.join(df_2)
  • Zusammenführen: Standardmäßig gleiche Spaltennamen (Wenn kein gleicher Spaltenname vorhanden ist, wird im Standardmodus ein Fehler ausgegeben.)
df_1.merge(df_2)
  • on Parameter hat in beiden Fällen unterschiedliche Bedeutung
df_1.merge(df_2, on='column_1')

df_1.join(df_2, on='column_1') // It will throw error
df_1.join(df_2.set_index('column_1'), on='column_1')
Hart
quelle
2

Analog zu SQL "Pandas-Zusammenführung ist eine äußere / innere Verbindung und Pandas-Verbindung ist eine natürliche Verbindung". Wenn Sie in Pandas zusammenführen verwenden, möchten Sie daher angeben, welche Art von SQL-Join Sie verwenden möchten. Wenn Sie Pandas-Join verwenden, möchten Sie wirklich eine passende Spaltenbezeichnung haben, um sicherzustellen, dass er verknüpft wird

Kaustubh J.
quelle