Jaka jest różnica między łączeniem i łączeniem w Pandach?


208

Załóżmy, że mam dwie takie ramki danych:

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

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

Chcę je scalić, więc próbuję czegoś takiego:

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

I cieszę się

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

Ale próbuję użyć metody łączenia, w którą, jak wierzyłem, podobna jest sytuacja.

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

I dostaję to:

//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: 

czego mi brakuje?


4
Specyficznym problemem jest to, że mergełączy kolumny z leftkolumnami right, co jest tym, czego chcesz, ale join(... on=[...])łączy kolumny z leftkluczami indeksu right, co nie jest tym, czego chcesz. Zobacz moją odpowiedź poniżej, aby uzyskać więcej informacji.
Matthias Fripp

3
DataFrame.join () zawsze chce dopasować indeksy lub klucze dzwoniącego (określone przez onopcję) do otherindeksów. Pamiętaj, indeksy dla dołączenia. Chociaż merge () jest bardziej ogólną metodą.
Jiapeng Zhang

Odpowiedzi:


87

Zawsze używam joinindeksów:

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

Tę samą funkcjonalność można uzyskać za pomocą mergenastępujących kolumn:

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

Błąd wydaje się polegać na tym, że oczekuje, że indeks wielokrotny na righttej samej głębokości ma długość on. To ma dla mnie sens. Mogę zaakceptować, że semantyka jest inna. Ale chciałbym wiedzieć, czy mogę uzyskać to samo zachowanie z df.join
munk

346

pandas.merge() to podstawowa funkcja używana dla wszystkich zachowań scalania / łączenia.

Ramki danych zapewniają metody pandas.DataFrame.merge()i pandas.DataFrame.join()jako wygodny sposób dostępu do możliwości pandas.merge(). Na przykład df1.merge(right=df2, ...)jest równoważne z pandas.merge(left=df1, right=df2, ...).

Oto główne różnice między df.join()i df.merge():

  1. wyszukiwanie w prawej tabeli: df1.join(df2)zawsze łączy się poprzez indeks df2, ale df1.merge(df2)może łączyć się z jedną lub więcej kolumnami df2(domyślnie) lub z indeksem df2(z right_index=True).
  2. odnośnik w lewej tabeli: domyślnie df1.join(df2)używa indeksu df1i df1.merge(df2)używa kolumn (y) df1. Można to zastąpić, określając df1.join(df2, on=key_or_keys)lub df1.merge(df2, left_index=True).
  3. lewe vs wewnętrzne złączenie: df1.join(df2)domyślnie wykonuje lewe łączenie (zachowuje wszystkie rzędy df1), ale df.mergedomyślnie wykonuje łączenie wewnętrzne (zwraca tylko pasujące wiersze df1i df2).

Tak więc ogólne podejście polega na użyciu pandas.merge(df1, df2)lub df1.merge(df2). Ale w wielu typowych sytuacjach (utrzymywanie wszystkich wierszy df1i łączenie z indeksem w środku df2) możesz zapisać trochę pisania, używając df1.join(df2)zamiast tego.

Kilka uwag na temat tych zagadnień z dokumentacji na stronie http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging :

merge jest funkcją w przestrzeni nazw pand i jest również dostępna jako metoda instancji DataFrame, przy czym wywołanie DataFrame jest domyślnie uważane za lewy obiekt w złączeniu.

Metoda pokrewna DataFrame.joinużywa mergewewnętrznie do łączenia indeksów i indeksów w kolumnach, ale domyślnie łączy się w indeksach, zamiast próbować łączyć się we wspólnych kolumnach (zachowanie domyślne dla merge). Jeśli dołączasz do indeksu, możesz chcieć DataFrame.joinzaoszczędzić trochę pisania.

...

Te dwa wywołania funkcji są całkowicie równoważne:

left.join(right, on=key_or_keys)
pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)

19
To zdecydowanie powinna być zaakceptowana odpowiedź! Dzięki za
dokładne

@Matthias Fripp, Być może dla bardziej doświadczonych jest rzeczą oczywistą, ale można też powiedzieć, że „wyszukiwanie w prawej tabeli: df1.join (df2) można zastąpić df1.join (df2, on = key_or_keys?
spacedustpi

@spacedustpi, myślę, że mówisz, że możesz użyć, on=key_or_keysaby zmienić sposób znajdowania wierszy w odpowiedniej tabeli. Tak jednak nie jest. onArgumentu zmienia się wyszukiwanie na lewym stołem ( df1) z indeksem do kolumny (S). Jednak nawet z tym argumentem odpowiednia tabela ( df2) zostanie dopasowana poprzez jej indeks. (Zobacz ostatni przykład powyżej.)
Matthias Fripp

Pandy mają kilka metod radzenia sobie z tymi sytuacjami, między innymi łączenie, łączenie, dołączanie, łączenie, łączenie, łączenie_pierwsze. Rzuć okiem na każdy z nich, aby rzucić okiem na to, który najlepiej pasuje do Twojej sytuacji
xiaxio

13

Uważam, że join()to tylko wygodna metoda. Spróbuj df1.merge(df2)zamiast tego, co pozwala określić left_oni 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

11

Z tej dokumentacji

pandy zapewniają pojedynczą funkcję scalania jako punkt wejścia dla wszystkich standardowych operacji łączenia bazy danych między obiektami DataFrame:

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)

I :

DataFrame.joinjest wygodną metodą łączenia kolumn dwóch potencjalnie różnie indeksowanych DataFrame w jeden wynik DataFrame. Oto bardzo prosty przykład: wyrównanie danych znajduje się w indeksach (etykietach wierszy). To samo zachowanie można osiągnąć za pomocą scalania oraz dodatkowych argumentów instruujących go do użycia indeksów:

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

8

Jedną z różnic jest to, że mergetworzy nowy indeks i joinutrzymuje indeks z lewej strony. Może to mieć duży wpływ na twoje późniejsze transformacje, jeśli błędnie założysz, że twój indeks się nie zmienia merge.

Na przykład:

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

To jest poprawne. Jeśli scalimy dwie ramki danych w kolumnach innych niż indeksy, otrzymamy nowy indeks, ale jeśli scalimy indeksy obu ramek danych, otrzymamy ramkę danych o tym samym indeksie. Aby więc uzyskać ten sam indeks po scaleniu, możemy ustawić kolumny jako nasz indeks (na którym chcemy scalić) dla obu ramek danych, a następnie scalić ramki danych w nowo utworzonym indeksie.
hasan najeeb

Bardzo wnikliwy. Nigdy nie potrzebowałem indeksowania (zwykle po prostu resetuję indeks), ale w niektórych przypadkach może to mieć duże znaczenie.
Irene

4
  • Dołącz: Indeks domyślny (jeśli jakakolwiek nazwa kolumny spowoduje wygenerowanie błędu w trybie domyślnym, ponieważ nie zdefiniowałeś lsuffix lub rsuffix))
df_1.join(df_2)
  • Scal: Domyślne te same nazwy kolumn (jeśli żadna nazwa tej samej kolumny nie spowoduje błędu w trybie domyślnym)
df_1.merge(df_2)
  • on parametr ma inne znaczenie w obu przypadkach
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')

2

Mówiąc analogicznie do SQL „Scalanie Pandas oznacza łączenie zewnętrzne / wewnętrzne, a łączenie Pandas jest łączeniem naturalnym”. Dlatego kiedy używasz scalania w pandach, chcesz określić, jakiego rodzaju złączenia sqlish chcesz użyć, podczas gdy używając pand, naprawdę chcesz mieć pasującą etykietę kolumny, aby upewnić się, że się łączy

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.