Pandas Merging 101

365
  • ¿Cómo realizar una unión ( LEFT| RIGHT| FULL) ( INNER| OUTER) con pandas?
  • ¿Cómo agrego NaNs para las filas que faltan después de la fusión?
  • ¿Cómo me deshago de NaNs después de la fusión?
  • ¿Puedo fusionarme en el índice?
  • Cruz unirse con pandas?
  • ¿Cómo fusiono múltiples DataFrames?
  • merge? join? concat? update? ¿OMS? ¿Qué? ¡¿Por qué?!

... y más. He visto estas preguntas recurrentes preguntando sobre varias facetas de la funcionalidad de fusión de pandas. La mayor parte de la información sobre la fusión y sus diversos casos de uso hoy en día está fragmentada en docenas de publicaciones mal redactadas e inescrutables. El objetivo aquí es recopilar algunos de los puntos más importantes para la posteridad.

Este QnA está destinado a ser la próxima entrega de una serie de útiles guías de usuario sobre modismos de pandas comunes (vea esta publicación sobre pivote y esta publicación sobre concatenación , que abordaré más adelante).

Tenga en cuenta que esta publicación no pretende ser un reemplazo de la documentación , ¡así que léala también! Algunos de los ejemplos se toman de allí.

cs95
fuente

Respuestas:

520

Esta publicación tiene como objetivo dar a los lectores una introducción sobre la fusión con sabor a SQL con pandas, cómo usarla y cuándo no usarla.

En particular, esto es por lo que pasará esta publicación:

  • Lo básico: tipos de combinaciones (IZQUIERDA, DERECHA, EXTERIOR, INTERIOR)

    • fusionándose con diferentes nombres de columna
    • evitar duplicar la columna de combinación de claves en la salida
  • Fusionar con índice bajo diferentes condiciones
    • usando efectivamente su índice nombrado
    • fusionar clave como el índice de uno y la columna de otro
  • Combinaciones múltiples en columnas e índices (únicos y no únicos)
  • Alternativas notables a mergeyjoin

Lo que esta publicación no pasará:

  • Debates y tiempos relacionados con el rendimiento (por ahora). Menciones en su mayoría notables de mejores alternativas, donde sea apropiado.
  • Manejo de sufijos, eliminación de columnas adicionales, cambio de nombre de salidas y otros casos de uso específicos. Hay otras publicaciones (leer: mejores) que se ocupan de eso, ¡así que descúbrelo!

Nota
La mayoría de los ejemplos tienen por defecto las operaciones INNER JOIN mientras demuestran varias características, a menos que se especifique lo contrario.

Además, todos los DataFrames aquí se pueden copiar y replicar para que pueda jugar con ellos. Además, vea esta publicación sobre cómo leer DataFrames desde su portapapeles.

Por último, todas las representaciones visuales de las operaciones de JOIN se han dibujado a mano con Google Drawings. Inspiración de aquí .

¡Basta de hablar, solo muéstrame cómo usar merge!

Preparar

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

En aras de la simplicidad, la columna clave tiene el mismo nombre (por ahora).

Una UNIÓN INTERNA está representada por

Tenga en cuenta que
esto, junto con las próximas cifras, siguen esta convención:

  • el azul indica filas que están presentes en el resultado de la fusión
  • rojo indica filas que están excluidas del resultado (es decir, eliminadas)
  • verde indica valores perdidos que se reemplazan con NaN en el resultado

Para realizar una mergeUNIÓN INTERNA, llame al DataFrame izquierdo, especificando el DataFrame derecho y la clave de unión (como mínimo) como argumentos.

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

Esto devuelve solo filas de lefty rightque comparten una clave común (en este ejemplo, "B" y "D").

Una IZQUIERDA EXTERIOR IZQUIERDA , o IZQUIERDA UNIÓN está representada por

Esto se puede realizar especificando how='left'.

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

Observe cuidadosamente la colocación de NaNs aquí. Si especifica how='left', solo leftse usan las claves de , y los datos que faltan rightse reemplazan por NaN.

Y de manera similar, para una DERECHA EXTERIOR UNIR , o DERECHA UNIR que es ...

... especifique how='right':

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

Aquí, rightse usan claves de , y los datos que faltan leftse reemplazan por NaN.

Finalmente, para la FULL OUTER JOIN , dada por

especifique how='outer'.

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

Esto usa las claves de ambos marcos, y se insertan NaNs para las filas que faltan en ambos.

La documentación resume estas diversas fusiones muy bien:

ingrese la descripción de la imagen aquí

Otras uniones - Exclusión izquierda, exclusión derecha y exclusión completa / ANTI

Si necesita unir a la izquierda excluyendo y unir a la derecha excluyendo uniones en dos pasos.

Para IZQUIERDA-Excluyendo JOIN, representado como

Comience realizando una IZQUIERDA EXTERIOR IZQUIERDA y luego filtrando (¡excluyendo!) Filas que provienen leftsolo de,

(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

Dónde,

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

Y de manera similar, para una UNIÓN DERECHA,

(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

Por último, si debe realizar una fusión que solo retiene las claves de la izquierda o la derecha, pero no ambas (IOW, realizar un ANTI-JOIN ),

Puedes hacer esto de manera similar:

(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

Nombres diferentes para columnas clave

Si las columnas clave se nombran de manera diferente, por ejemplo, lefttiene keyLefty righttiene en keyRightlugar de, keyentonces deberá especificar left_ony right_oncomo argumentos en lugar de 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

Evitar duplicar la columna clave en la salida

Al fusionar keyLeftdesde lefty keyRightdesde right, si solo desea cualquiera de los dos ( keyLefto keyRightno ambos) en la salida, puede comenzar configurando el índice como un paso preliminar.

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

Compare esto con la salida del comando justo antes (es decir, la salida de left2.merge(right2, left_on='keyLeft', right_on='keyRight', how='inner')), notará keyLeftque falta. Puede averiguar qué columna mantener en función del índice de marco que se establece como la clave. Esto puede importar cuando, por ejemplo, realice alguna operación OUTER JOIN.

Fusionar solo una columna de uno de los DataFrames

Por ejemplo, considere

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

Si debe fusionar solo "new_val" (sin ninguna de las otras columnas), generalmente puede subconjuntar columnas antes de fusionar:

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

  key     value  newcol
0   B  0.400157       0
1   D  2.240893       1

Si está haciendo una IZQUIERDA EXTERIOR IZQUIERDA, una solución más eficaz implicaría map:

# 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

Como se mencionó, esto es similar a, pero más rápido que

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

Fusionar en múltiples columnas

Para unirse en más de una columna, especifique una lista para on(o left_ony right_on, según corresponda).

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

O, en caso de que los nombres sean diferentes,

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

Otras merge*operaciones y funciones útiles.

Esta sección solo cubre los conceptos básicos y está diseñada para abrir el apetito. Para más ejemplos y casos, consulte la documentación sobre merge, joinyconcat así como los enlaces a las especificaciones de función.


Basado en índice * -JOIN (+ índice-columna merges)

Preparar

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

Por lo general, una fusión en el índice se vería así:

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


         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Soporte para nombres de índice

Si el índice se nombra, a continuación, v0.23 usuarios también pueden especificar el nombre del nivel de on(o left_on, y right_onsi es necesario).

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

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Fusión en el índice de uno, columna (s) de otro

Es posible (y bastante simple) usar el índice de uno y la columna de otro para realizar una fusión. Por ejemplo,

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

O viceversa ( right_on=...y 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

En este caso especial, leftse nombra el índice para , por lo que también puede usar el nombre del índice con left_on, de esta manera:

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
Además de estos, hay otra opción sucinta. Puede usar DataFrame.joinqué valores predeterminados se unen en el índice. DataFrame.joinhace una IZQUIERDA EXTERIOR IZQUIERDA por defecto, por lo que how='inner'es necesario aquí.

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

         value_x   value_y
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Tenga en cuenta que necesitaba especificar los argumentos lsuffixy rsuffixya que de joinlo contrario se produciría un error:

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

Dado que los nombres de las columnas son iguales. Esto no sería un problema si tuvieran un nombre diferente.

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

        leftvalue     value
idxkey                     
B       -0.402655  0.543843
D       -0.524349  0.013135

pd.concat
Por último, como alternativa para las uniones basadas en índices, puede usar pd.concat:

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

           value     value
idxkey                    
B      -0.402655  0.543843
D      -0.524349  0.013135

Omita join='inner'si necesita una UNIÓN COMPLETA DE EXTERIOR (el valor predeterminado):

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

Para obtener más información, consulte esta publicación canónica pd.concatde @piRSquared .


Generalizando: mergeing múltiples marcos de datos

A menudo, la situación surge cuando se combinan varios DataFrames. Ingenuamente, esto se puede hacer encadenando mergellamadas:

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

Sin embargo, esto rápidamente se sale de control para muchos DataFrames. Además, puede ser necesario generalizar para un número desconocido de marcos de datos.

Aquí presento pd.concatlas uniones multidireccionales en claves únicas y DataFrame.joinlas uniones multidireccionales en claves no únicas . Primero, la configuración.

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

Combinación de múltiples vías en claves únicas (o índice)

Si sus claves (aquí, la clave podría ser una columna o un índice) son únicas, entonces puede usarlas pd.concat. Tenga en cuenta que pd.concatune DataFrames en el índice .

# 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

Omita join='inner'para una UNIÓN COMPLETA EXTERIOR. Tenga en cuenta que no puede especificar uniones EXTERIORES IZQUIERDA o DERECHA (si las necesita, use join, como se describe a continuación).

Combinación de múltiples vías en claves con duplicados

concatEs rápido, pero tiene sus defectos. No puede manejar duplicados.

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)

En esta situación, podemos usarlo joinya que puede manejar claves no únicas (tenga en cuenta que joinune DataFrames en su índice; llama mergebajo el capó y hace una IZQUIERDA EXTERIOR IZQUIERDA a menos que se especifique lo contrario).

# 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
cs95
fuente
49

Una vista visual suplementaria de pd.concat([df0, df1], kwargs). Tenga en cuenta que el significado de kwarg axis=0o axis=1no es tan intuitivo como df.mean()odf.apply(func)


en pd.concat ([df0, df1])

eliu
fuente
99
Este es un buen diagrama. ¿Puedo preguntar cómo lo produjiste?
cs95
66
"insert ==> drawing ... ==> new" integrado en google doc (a partir de 2019-mayo). Pero, para ser claros: la única razón por la que utilicé google doc para esta imagen es porque mis notas están almacenadas en google doc, y me gustaría una imagen que pueda modificarse rápidamente dentro de google doc. En realidad, ahora que lo mencionaste, la herramienta de dibujo de Google Docs es bastante ordenada.
eliu
Wow esto es genial. Viniendo del mundo SQL, la unión "vertical" no es una unión en mi cabeza, ya que la estructura de la tabla siempre está fija. Ahora incluso piense que los pandas deberían consolidarse concaty mergecon un parámetro de dirección siendo horizontalo vertical.
Ovnis el
2
@Ufos ¿No es eso exactamente axis=1y qué axis=0es?
cs95
2
Sí, hay ahora mergey concaty el eje y lo que sea. Sin embargo, como muestra @eliu, todo es el mismo concepto de fusión con "izquierda" y "derecha" y "horizontal" o "vertical". Yo, personalmente, tengo que revisar la documentación cada vez que tengo que recordar qué "eje" es 0y cuál es 1.
Ovnis