¿Cuál es la diferencia entre unirse y fusionarse en Pandas?

208

Supongamos que tengo dos DataFrames así:

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

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

Quiero fusionarlos, así que intento algo como esto:

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

Y estoy feliz

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

Pero estoy tratando de usar el método de unión, que me han hecho creer que es bastante similar.

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

Y entiendo esto:

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

¿Qué me estoy perdiendo?

Munk
fuente
44
El problema específico aquí es que mergeune columnas de lefta columnas de right, que es lo que desea, pero join(... on=[...])une columnas de leftclaves de índice de right, que no es lo que desea. Vea mi respuesta a continuación para más detalles.
Matthias Fripp
3
DataFrame.join () siempre quiere hacer coincidir los índices o claves de la persona que llama (especificado por la onopción) con los otheríndices de 's. Recuerde, índices para unirse. Mientras que merge () es un método más genérico.
Jiapeng Zhang

Respuestas:

87

Siempre uso joinen índices:

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

Se puede tener la misma funcionalidad usando mergelas siguientes columnas:

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
fuente
El error parece estar diciendo que espera que el índice múltiple rightsea ​​de la misma profundidad que la longitud on. Eso tiene sentido para mí. Puedo aceptar que la semántica es diferente. Pero me gustaría saber si puedo conseguir que el mismo comportamiento con df.join
Munk
346

pandas.merge() es la función subyacente utilizada para todos los comportamientos de fusión / unión.

Los marcos de datos proporcionan los métodos pandas.DataFrame.merge()y pandas.DataFrame.join()como una forma conveniente de acceder a las capacidades de pandas.merge(). Por ejemplo, df1.merge(right=df2, ...)es equivalente a pandas.merge(left=df1, right=df2, ...).

Estas son las principales diferencias entre df.join()y df.merge():

  1. búsqueda en la tabla derecha: df1.join(df2)siempre se une a través del índice de df2, pero df1.merge(df2)puede unirse a una o más columnas de df2(predeterminado) o al índice de df2(con right_index=True).
  2. búsqueda en la tabla de la izquierda: por defecto, df1.join(df2)usa el índice df1y las df1.merge(df2)columnas de df1. Eso se puede anular especificando df1.join(df2, on=key_or_keys)o df1.merge(df2, left_index=True).
  3. combinación izquierda / interior: df1.join(df2)realiza una combinación izquierda de forma predeterminada (mantiene todas las filas de df1), pero df.mergeuna combinación interna de forma predeterminada (solo devuelve filas coincidentes de df1y df2).

Entonces, el enfoque genérico es usar pandas.merge(df1, df2)o df1.merge(df2). Pero para una serie de situaciones comunes (mantener todas las filas df1y unirse a un índice df2), puede guardar algo de tipeo utilizando en su df1.join(df2)lugar.

Algunas notas sobre estos temas de la documentación en http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging :

merge es una función en el espacio de nombres de pandas, y también está disponible como un método de instancia de DataFrame, con el DataFrame de llamada implícitamente considerado el objeto izquierdo en la unión.

El DataFrame.joinmétodo relacionado , se usa mergeinternamente para las uniones index-on-index e index-on-column (s), pero se une a los índices de forma predeterminada en lugar de intentar unirse a columnas comunes (el comportamiento predeterminado para merge). Si se está uniendo en el índice, puede utilizarlo DataFrame.joinpara ahorrar algo de escritura.

...

Estas dos llamadas a funciones son completamente equivalentes:

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
fuente
19
¡Esta definitivamente debería ser la respuesta aceptada! Gracias por la explicación detallada
Yohan Obadia
@Matthias Fripp, tal vez para los más experimentados no hace falta decirlo, pero también se podría decir que "buscar en la tabla derecha: df1.join (df2) se puede reemplazar a df1.join (df2, on = key_or_keys?
spacedustpi
@spacedustpi, creo que está diciendo que puede usar on=key_or_keyspara cambiar la forma en que se encuentran las filas en la tabla correcta. Sin embargo, ese no es realmente el caso. El onargumento cambia la búsqueda en la tabla izquierda ( df1) de índice a columna (s). Sin embargo, incluso con este argumento, la tabla correcta ( df2) se comparará a través de su índice. (Vea el último ejemplo anterior.)
Matthias Fripp
Pandas tiene varios métodos para lidiar con estas situaciones, entre ellas fusionar, unir, agregar, concat, combinar, combine_first. Eche un vistazo a cada uno de estos para tener una idea de cuál sería el mejor para su situación
xiaxio
13

Creo que join()es solo un método de conveniencia. Pruebe en su df1.merge(df2)lugar, lo que le permite especificar left_ony 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
Noé
fuente
11

De esta documentación

pandas proporciona una función única, fusionar, como punto de entrada para todas las operaciones de unión de bases de datos estándar entre objetos 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)

Y:

DataFrame.joines un método conveniente para combinar las columnas de dos marcos de datos potencialmente indexados de manera diferente en un solo marco de datos de resultados. Aquí hay un ejemplo muy básico: la alineación de datos aquí está en los índices (etiquetas de fila). Este mismo comportamiento se puede lograr mediante la combinación más argumentos adicionales que le indican que use los índices:

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

Una de las diferencias es que mergeestá creando un nuevo índice y joinestá manteniendo el índice del lado izquierdo. Puede tener una gran consecuencia en sus transformaciones posteriores si asume erróneamente que su índice no cambia con merge.

Por ejemplo:

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
fuente
Eso es correcto. Si fusionamos los dos marcos de datos en columnas que no sean índices, obtendremos un nuevo índice, pero si combinamos los índices de ambos marcos de datos, obtendremos un marco de datos con el mismo índice. Por lo tanto, para obtener el mismo índice después de la fusión, podemos hacer que las columnas sean nuestro índice (en el que queremos fusionar) para ambos marcos de datos y luego fusionar los marcos de datos en el índice recién creado.
hasan najeeb
Muy perspicaz. Nunca he necesitado la indexación (normalmente solo restablezco el índice) pero esto podría hacer una gran diferencia en algunos casos.
Irene
4
  • Unir: Índice predeterminado (si tiene el mismo nombre de columna, arrojará un error en el modo predeterminado porque no ha definido lsuffix o rsuffix))
df_1.join(df_2)
  • Fusionar: los mismos nombres de columna predeterminados (si no hay el mismo nombre de columna arrojará un error en el modo predeterminado)
df_1.merge(df_2)
  • on parámetro tiene un significado diferente en ambos casos
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')
Duro
fuente
2

Para decirlo de manera análoga a SQL "La fusión de Pandas es una unión externa / interna y la unión de Pandas es una unión natural". Por lo tanto, cuando usa la combinación en pandas, desea especificar qué tipo de combinación sqlish desea usar, mientras que cuando usa la combinación de pandas, realmente desea tener una etiqueta de columna coincidente para asegurarse de que se una

Kaustubh J
fuente