Różnica (y) między merge () i concat () w pandach

85

Jaka jest zasadnicza różnica (y) między pd.DataFrame.merge()i pd.concat()?

Jak dotąd znalazłem to, proszę o komentarz, jak kompletne i dokładne jest moje zrozumienie:

  • .merge()może używać tylko kolumn (plus indeksów wierszy) i jest semantycznie odpowiedni dla operacji w stylu bazy danych. .concat()może być używany z każdą osią, używając tylko indeksów, i daje możliwość dodania indeksu hierarchicznego.

  • Nawiasem mówiąc, pozwala to na następującą nadmiarowość: obie mogą łączyć dwie ramki danych przy użyciu indeksów wierszy.

  • pd.DataFrame.join() oferuje jedynie skrót dla podzbioru przypadków użycia .merge()

(Pandy świetnie radzą sobie z bardzo szerokim spektrum przypadków użycia w analizie danych. Przeglądanie dokumentacji w celu ustalenia, jaki jest najlepszy sposób wykonania określonego zadania, może być nieco zniechęcające).

Dzwonki wietrzne
źródło
3
Również powiązane: stackoverflow.com/a/37891437/1972495 dyskusja wokół .merge()i .join().
WindChimes,
2
W przypadku scalania, łączenia i łączenia uważam, że ta odpowiedź jest bardzo jasna, w jaki sposób można ich wszystkich użyć do zrobienia tego samego (wydają się być po prostu alternatywnym interfejsem do tej samej funkcjonalności). Dzięki twojemu pytaniu (i odpowiedzi, którą linkujesz w komentarzu) wiem, że wreszcie rozumiem, jak łączenie i dołączanie są powiązane. Wciąż nie jest dla mnie jasne, czy concat używa innej implementacji, czy nie (chyba będę musiał spojrzeć na kod źródłowy ...)
pietroppeter

Odpowiedzi:

77

Bardzo duża różnica poziomów merge()jest używana do łączenia dwóch (lub więcej) ramek danych na podstawie wartości wspólnych kolumn (można również używać indeksów, używać left_index=Truei / lub right_index=True) i concat()służy do dołączania jednej (lub więcej) ramek danych poniżej drugiego (lub na boki, w zależności od tego, czy axisopcja jest ustawiona na 0 czy 1).

join()służy do łączenia 2 ramek danych na podstawie indeksu; zamiast używać merge()z opcją, left_index=Truektórej możemy użyć join().

Na przykład:

df1 = pd.DataFrame({'Key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})

df1:
   Key  data1
0   b   0
1   b   1
2   a   2
3   c   3
4   a   4
5   a   5
6   b   6

df2 = pd.DataFrame({'Key': ['a', 'b', 'd'], 'data2': range(3)})

df2:
    Key data2
0   a   0
1   b   1
2   d   2

#Merge
# The 2 dataframes are merged on the basis of values in column "Key" as it is 
# a common column in 2 dataframes

pd.merge(df1, df2)

   Key data1 data2
0   b    0    1
1   b    1    1
2   b    6    1
3   a    2    0
4   a    4    0
5   a    5    0

#Concat
# df2 dataframe is appended at the bottom of df1 

pd.concat([df1, df2])

   Key data1 data2
0   b   0     NaN
1   b   1     NaN
2   a   2     NaN
3   c   3     NaN
4   a   4     NaN
5   a   5     NaN
6   b   6     NaN
0   a   Nan   0
1   b   Nan   1
2   d   Nan   2
Abhishek Sawant
źródło
Tak, oznacza to, że argument howw mergepracach i oznaczają zupełnie inny niż to, co robi w concat?
Hemanth Bakaya
11

pd.concatprzyjmuje Iterablejako argument. W związku z tym nie może przyjmować DataFrames bezpośrednio jako argumentu. Również Dimensionelementy DataFramepowinny pasować wzdłuż osi podczas konkatenacji.

pd.mergemoże przyjąć DataFrames jako argument i jest używany do łączenia dwóch DataFrames z tymi samymi kolumnami lub indeksem, czego nie można zrobić, pd.concatponieważ spowoduje wyświetlenie powtórzonej kolumny w DataFrame.

Natomiast złączenia można użyć do połączenia dwóch DataFramez różnymi indeksami.

Piyush Malhotra Nova_Outlaw
źródło
7
Podoba mi się ta odpowiedź, ponieważ stwierdza, że ​​wymiary powinny być zgodne podczas konkatenacji. concatto nic innego jak przyklejenie kilku ramek danych jedna nad drugą / obok siebie. Nie jest świadomy treści w tym sensie, że po prostu pokaże tę samą kolumnę dwa razy. Natomiast mergefaktycznie połączy kolumny, gdy będą takie same.
jorijnsmit
2
Myślę, że to nieprawda. Nawet powyższa odpowiedź (autorstwa @Abhishek Sawant) podaje przykład, concatgdzie wymiary nie pasują.
michcio1234
7

Obecnie próbuję zrozumieć zasadniczą różnicę (y) między pd.DataFrame.merge()a pd.concat().

Fajne pytanie. Podstawowa różnica:

pd.concat działa na obu osiach.

Inną różnicą jest to, że pd.concatma tylko wewnętrzne domyślne i zewnętrzne łączenia, podczas gdy pd.DataFrame.merge()ma lewe , prawe , zewnętrzne i wewnętrzne domyślne łączenia.

Trzecia zauważalna inna różnica to: pd.DataFrame.merge()ma możliwość ustawienia sufiksów kolumn podczas łączenia kolumn o tej samej nazwie, podczas gdy pd.concatnie jest to możliwe.


Z pd.concatdomyślnie jesteś w stanie układać wiersze wielu dataframes ( axis=0) i po ustawieniu axis=1wtedy naśladować pd.DataFrame.merge()funkcji.

Kilka przydatnych przykładów pd.concat:

df2=pd.concat([df]*2, ignore_index=True) #double the rows of a dataframe

df2=pd.concat([df, df.iloc[[0]]]) # add first row to the end

df3=pd.concat([df1,df2], join='inner', ignore_index=True) # concat two df's
prosti
źródło
5

Na wysokim poziomie:

  • .concat()po prostu układa wiele DataFramerazem w pionie lub zszywa poziomo po wyrównaniu na indeksie
  • .merge()najpierw wyrównuje dwie DataFramewybrane wspólne kolumny lub indeks, a następnie wybiera pozostałe kolumny z wyrównanych wierszy każdej z nich DataFrame.

A dokładniej .concat():

  • Jest funkcją pand najwyższego poziomu
  • Łączy dwie lub więcej pandy DataFrame pionowo lub poziomo
  • Wyrównuje tylko do indeksu podczas łączenia w poziomie
  • Błędy, gdy którykolwiek z DataFramezawiera zduplikowany indeks.
  • Domyślnie sprzężenie zewnętrzne z opcją sprzężenia wewnętrznego

Oraz .merge():

  • Istnieje zarówno jako funkcja pandy najwyższego poziomu, jak i DataFramemetoda (od pandy 1.0)
  • Łączy dokładnie dwa w DataFramepoziomie
  • Wyrównuje połączeń DataFrame„s kolumnowej (S), albo z innym indeksem DataFrame” a kolumna (-y) lub indeks
  • Obsługuje zduplikowane wartości w łączonych kolumnach lub indeksie , wykonując iloczyn kartezjański
  • Domyślnie sprzężenie wewnętrzne z opcjami dla lewego, zewnętrznego i prawego

Zwróć uwagę, że podczas wykonywania pd.merge(left, right), jeśli leftma dwa wiersze zawierające te same wartości z łączących się kolumn lub indeksu, każdy wiersz zostanie połączony z rightodpowiadającym mu wierszem ( wierszami ), dając w wyniku iloczyn kartezjański. Z drugiej strony, jeśli .concat()jest używany do łączenia kolumn, musimy upewnić się, że w żadnym z nich nie ma zduplikowanego indeksu DataFrame.

Praktycznie rzecz biorąc:

  • Rozważ .concat()najpierw przy łączeniu jednorodnych DataFrame, a .merge()najpierw rozważ łączenie komplementarne DataFrame.
  • Jeśli chcesz scalić w pionie, przejdź z .concat(). Jeśli chcesz scalić w poziomie za pomocą kolumn, użyj .merge(), które domyślnie łączą się na wspólnych kolumnach.

Źródła : Pandas 1.x Cookbook

Jake Wu
źródło
2

Główna różnica między scalaniem i konkatencją polega na tym, że funkcja merge umożliwia wykonywanie bardziej ustrukturyzowanego „łączenia” tabel, w których użycie konkatacji jest szersze i mniej ustrukturyzowane.

Łączyć

Odwołując się do dokumentacji , pd.DataFrame.mergeprzyjmuje się rację jako wymagany argument, który można uznać za łączenie lewej tabeli i prawej tabeli zgodnie z pewną wstępnie zdefiniowaną operacją łączenia. Zwróć uwagę na definicję parametru right .

Wymagane parametry

  • po prawej : DataFrame lub nazwana Series

Parametry opcjonalne

  • jak : {'left', 'right', 'external', 'inner'} default 'inner'
  • on : etykieta lub lista
  • left_on : etykieta lub lista lub podobne do tablicy
  • right_on : etykieta lub lista lub podobne do tablicy
  • left_index : bool, domyślnie False
  • right_index : bool, domyślnie False
  • sort : bool, default False
  • przyrostki : krotka z (str, str), domyślne ('_x', '_y')
  • copy : bool, domyślnie True
  • wskaźnik : bool lub str, domyślnie False
  • validate : str, opcjonalne

Ważne: pd.DataFrame.merge wymaga prawa do bycia pd.DataFramelub nazwanym pd.Seriesobiektem.

Wynik

  • Zwraca : DataFrame

Ponadto, jeśli sprawdzimy, jak poniżej znajduje się dokumentacja operacji scalania na pandach:

Wykonaj operację scalania bazy danych (SQL) między dwoma obiektami DataFrame lub Series, używając kolumn jako kluczy lub ich indeksów wierszy

Concat

Odnoszą się do dokumentacji z pd.concat, pierwszej nuty, że parametr nie jest nazwany któregokolwiek z tabeli, data_frame, seria, matrycy itp, ale OBJS zamiast. Oznacza to, że możesz przekazać wiele „kontenerów danych”, które są zdefiniowane jako:

Iterable[FrameOrSeriesUnion], Mapping[Optional[Hashable], FrameOrSeriesUnion]

Wymagane parametry

  • objs : sekwencja lub mapowanie obiektów Series lub DataFrame

Parametry opcjonalne

  • : {0 / 'indeks', 1 / 'kolumny'}, domyślnie 0
  • join : {'inner', 'external'}, domyślnie 'external'
  • ignore_index : bool, default False
  • klucze : sekwencja, domyślnie Brak
  • poziomy : lista sekwencji, wartość domyślna Brak
  • nazwy : lista, domyślnie Brak
  • verify_integrity : bool, default False
  • sort : bool, default False
  • copy : bool, domyślnie True

Wynik

  • Zwraca : obiekt, typ obiektów

Przykład

Kod

import pandas as pd

v1 = pd.Series([1, 5, 9, 13])
v2 = pd.Series([10, 100, 1000, 10000])
v3 = pd.Series([0, 1, 2, 3])

df_left = pd.DataFrame({
    "v1": v1,
    "v2": v2,
    "v3": v3
    })
df_right = pd.DataFrame({
    "v4": [5, 5, 5, 5],
    "v5": [3, 2, 1, 0]
    })


df_concat = pd.concat([v1, v2, v3])

# Performing operations on default

merge_result = df_left.merge(df_right, left_index=True, right_index=True)
concat_result = pd.concat([df_left, df_right], sort=False)
print(merge_result)
print('='*20)
print(concat_result)

Kod wyjściowy

   v1     v2  v3  v4  v5
0   1     10   0   5   3
1   5    100   1   5   2
2   9   1000   2   5   1
3  13  10000   3   5   0
====================
     v1       v2   v3   v4   v5
0   1.0     10.0  0.0  NaN  NaN
1   5.0    100.0  1.0  NaN  NaN
2   9.0   1000.0  2.0  NaN  NaN
3  13.0  10000.0  3.0  NaN  NaN
0   NaN      NaN  NaN  5.0  3.0
1   NaN      NaN  NaN  5.0  2.0
2   NaN      NaN  NaN  5.0  1.0

Możesz jednak osiągnąć pierwsze wyjście (scalenie) z konkatacją poprzez zmianę parametru osi

concat_result = pd.concat([df_left, df_right], sort=False, axis=1)

Obserwuj następujące zachowanie,

concat_result = pd.concat([df_left, df_right, df_left, df_right], sort=False)

wyjścia;

     v1       v2   v3   v4   v5
0   1.0     10.0  0.0  NaN  NaN
1   5.0    100.0  1.0  NaN  NaN
2   9.0   1000.0  2.0  NaN  NaN
3  13.0  10000.0  3.0  NaN  NaN
0   NaN      NaN  NaN  5.0  3.0
1   NaN      NaN  NaN  5.0  2.0
2   NaN      NaN  NaN  5.0  1.0
3   NaN      NaN  NaN  5.0  0.0
0   1.0     10.0  0.0  NaN  NaN
1   5.0    100.0  1.0  NaN  NaN
2   9.0   1000.0  2.0  NaN  NaN
3  13.0  10000.0  3.0  NaN  NaN
0   NaN      NaN  NaN  5.0  3.0
1   NaN      NaN  NaN  5.0  2.0
2   NaN      NaN  NaN  5.0  1.0
3   NaN      NaN  NaN  5.0  0.0

, którego nie można wykonać podobnej operacji z scalaniem, ponieważ zezwala tylko na pojedynczą ramkę DataFrame lub nazwaną Series.

merge_result = df_left.merge([df_right, df_left, df_right], left_index=True, right_index=True)

wyjścia;

TypeError: Can only merge Series or DataFrame objects, a <class 'list'> was passed

Wniosek

Jak już być może zauważyłeś, dane wejściowe i wyjściowe mogą różnić się między „scalaniem” i „łączeniem”.

Jak wspomniałem na początku, pierwszą (główną) różnicą jest to, że "merge" wykonuje bardziej ustrukturyzowane złączenie z zestawem ograniczonych obiektów i parametrów, gdzie "concat" wykonuje mniej ścisłe / szersze złączenie z szerszym zestawem obiektów i parametrów.

Podsumowując, scalanie jest mniej tolerancyjne na zmiany / (dane wejściowe), a „konkatacja” jest luźniejsze / mniej wrażliwe na zmiany / (dane wejściowe). Możesz osiągnąć „scalanie” za pomocą „konkatacji”, ale nie zawsze jest odwrotnie.

Operacja „Scal” wykorzystuje kolumny ramek danych (lub nazwy pd.Seriesobiektu) lub indeksy wierszy, a ponieważ używa tylko tych jednostek, wykonuje poziome scalanie ramek danych lub serii i nie stosuje w rezultacie operacji pionowych.

Jeśli chcesz zobaczyć więcej, możesz trochę zagłębić się w kod źródłowy;

zero
źródło
-2

domyślnie:
złączenie jest złączeniem lewostronnym z
podziałem na kolumny
pd. merge jest złączeniem wewnętrznym z podziałem na kolumny pd.concat jest złączeniem zewnętrznym z podziałem na wiersze

pd.concat:
pobiera iterowalne argumenty. Dlatego nie może bezpośrednio pobierać DataFrame (użyj [df, df2])
Wymiary DataFrame powinny być zgodne wzdłuż osi

Join i pd.merge:
mogą przyjmować argumenty DataFrame

Kliknij, aby zobaczyć zdjęcie, aby zrozumieć, dlaczego poniższy kod robi to samo

df1.join(df2)
pd.merge(df1, df2, left_index=True, right_index=True)
pd.concat([df1, df2], axis=1)
vicpal
źródło