INNER | ( LEFT | RIGHT | FULL ) OUTER ) JOIN con pandas?merge ? join ? concat ? update ? ¿Quién? ¿Qué? ¡¿Por qué?!... y más. He visto estas preguntas recurrentes 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.
Esta sesión de preguntas y respuestas está destinada a ser la próxima entrega de una serie de útiles guías de usuario sobre modismos comunes de pandas (consulte esta publicación sobre pivoting 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 están tomados de allí.
Para facilitar el acceso.
En esta respuesta, consideraré ejemplos prácticos.
El primero, es de pandas.concat .
El segundo, de fusionar dataframes del índice de uno y la columna de otro.
1 . pandas.concat
Considerando los siguientes DataFrames con los mismos nombres de columna:
Preco2018 con talla (8784,5)
Preco 2019 con talla (8760, 5)
Que tienen los mismos nombres de columna.
Puedes combinarlos usando pandas.concat , simplemente
import pandas as pd frames = [Preco2018, Preco2019] df_merged = pd.concat(frames)Lo que da como resultado un DataFrame con el siguiente tamaño (17544, 5)
Si quieres visualizar, termina funcionando así.
( Fuente )
2 . Combinar por columna e índice
En esta parte, consideraré un caso específico: si uno quiere fusionar el índice de un marco de datos y la columna de otro marco de datos.
Digamos que uno tiene el marco de datos Geo con 54 columnas, siendo una de las columnas los Data Fecha, que es de tipo datetime64[ns] .
Y el marco de datos Price que tiene una columna con el precio y el índice corresponde a las fechas
En este caso específico, para fusionarlos, uno usa pd.merge
merged = pd.merge(Price, Geo, left_index=True, right_on='Data')Lo que da como resultado el siguiente marco de datos
Esta publicación tratará los siguientes temas:
merge tiene deficiencias aquí) A menudo, la situación surge cuando se fusionan varios DataFrames. Ingenuamente, esto se puede hacer encadenando llamadas de merge :
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 tramas de datos.
Aquí presento pd.concat para uniones multidireccionales en claves únicas y DataFrame.join para 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] Si sus claves (aquí, la clave podría ser una columna o un índice) son únicas, entonces puede usar pd.concat . Tenga en cuenta que pd.concat se une a 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 EXTERNA COMPLETA. Tenga en cuenta que no puede especificar combinaciones EXTERNAS IZQUIERDA o DERECHA (si las necesita, use la combinación , que join describe a continuación).
concat es 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 usar join ya que puede manejar claves no únicas (tenga en cuenta que join une DataFrames en su índice; llama a merge bajo el capó y hace un LEFT OUTER JOIN 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.0Vaya a otros temas en Pandas Merging 101 para continuar aprendiendo:
* estás aquí
Esta publicación tratará los siguientes temas:
merge , join , concatHay algunas opciones, algunas más simples que otras dependiendo del caso de uso.
DataFrame.mergeconleft_indexyright_index(oleft_onyright_onusando índices de nombres)
- admite interior/izquierda/derecha/completo
- solo se pueden juntar dos a la vez
- admite uniones columna-columna, índice-columna, índice-índice
DataFrame.join(unirse en el índice)
- admite interior/izquierdo (predeterminado)/derecho/completo
- puede unir múltiples DataFrames a la vez
- admite uniones índice-índice
pd.concat(se une al índice)
- admite interior/completo (predeterminado)
- puede unir múltiples DataFrames a la vez
- admite uniones índice-índice
Configuración y conceptos básicos
import pandas as pd import numpy as np np.random.seed([3, 14]) left = pd.DataFrame(data={'value': np.random.randn(4)}, index=['A', 'B', 'C', 'D']) right = pd.DataFrame(data={'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.385076Por lo general, una combinación interna 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.013135Otras uniones siguen una sintaxis similar.
Alternativas notables
DataFrame.join como valor predeterminado las uniones en el índice. DataFrame.join realiza una UNIÓN EXTERNA IZQUIERDA de forma predeterminada, por lo que aquí es necesario how='inner' .
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 lsuffix y rsuffix ya que, de lo contrario, la join generarí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 los mismos. 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 se une al índice y puede unir dos o más DataFrames a la vez. Hace una combinación externa completa de forma predeterminada, por lo que aquí se requiere how='inner' .
pd.concat([left, right], axis=1, sort=False, join='inner') value value idxkey B -0.402655 0.543843 D -0.524349 0.013135 Para obtener más información sobre concat , consulte esta publicación .
Para realizar una unión interna usando el índice de la izquierda, la columna de la derecha, usará DataFrame.merge una combinación de left_index=True y right_on=... .
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 Otras uniones siguen una estructura similar. Tenga en cuenta que solo la merge puede realizar uniones de índice a columna. Puede unirse en varias columnas, siempre que el número de niveles de índice a la izquierda sea igual al número de columnas a la derecha.
join y concat no son capaces de fusiones mixtas. Deberá configurar el índice como un paso previo mediante DataFrame.set_index .
Si su índice tiene nombre, entonces desde pandas >= 0.23, DataFrame.merge le permite especificar el nombre del índice en on (o left_on y right_on según sea necesario).
left.merge(right, on='idxkey') value_x value_y idxkey B -0.402655 0.543843 D -0.524349 0.013135 Para el ejemplo anterior de fusión con el índice de la izquierda, la columna de la derecha, puede usar left_on con el nombre del índice de la izquierda:
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.013135Vaya a otros temas en Pandas Merging 101 para continuar aprendiendo:
* estás aquí
Estas animaciones podrían ser mejores para explicarte visualmente. Créditos: Garrick Aden-Buie tidyexplain repo
Esta publicación tiene como objetivo brindar a los lectores una introducción a la fusión con sabor a SQL con Pandas, cómo usarla y cuándo no usarla.
En particular, esto es lo que pasará en esta publicación:
Los conceptos básicos: tipos de uniones (IZQUIERDA, DERECHA, EXTERIOR, INTERIOR)
Lo que esta publicación (y otras publicaciones mías en este hilo) no pasará:
Nota La mayoría de los ejemplos predeterminados son operaciones INNER JOIN mientras muestran varias funciones, a menos que se especifique lo contrario.
Además, todos los DataFrames aquí se pueden copiar y replicar para que puedas 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 JOIN se han dibujado a mano con Dibujos de Google. Inspiración desde aquí .
merge ! 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.151357En aras de la simplicidad, la columna clave tiene el mismo nombre (por ahora).
Un INNER JOIN está representado por

Tenga en cuenta que esto, junto con las próximas cifras, siguen esta convención:
- azul indica filas que están presentes en el resultado de la combinación
- rojo indica filas que están excluidas del resultado (es decir, eliminadas)
- el verde indica valores faltantes que se reemplazan con
NaNs en el resultado
Para realizar un INNER JOIN, llame a merge en el 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 las filas de left y right que comparten una clave común (en este ejemplo, "B" y "D).
UNA UNIÓN EXTERNA IZQUIERDA , o UNIÓN IZQUIERDA 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 Tenga en cuenta cuidadosamente la ubicación de NaNs aquí. Si especifica how='left' , solo se usan las claves de left y los datos faltantes de la right se reemplazan por NaN.
Y de manera similar, para un RIGHT OUTER JOIN , o RIGHT JOIN que es...

... especificar 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í, se utilizan las claves de right y los datos faltantes de la left se reemplazan por NaN.
Finalmente, para el FULL OUTER JOIN , dado por

especificar 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.151357Esto usa las claves de ambos marcos y se insertan NaN para las filas que faltan en ambos.
La documentación resume muy bien estas diversas fusiones:
Si necesita LEFT-Excluyendo JOIN y RIGHT-Excluyendo JOIN en dos pasos.
Para LEFT-Excluyendo JOIN, representado como

Comience realizando una UNIÓN EXTERNA IZQUIERDA y luego filtrando (¡excluyendo!) las filas que provienen solo de left ,
(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 NaNDonde,
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 bothY de manera similar, para un RIGHT-Excluyendo JOIN,

(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.151357Por último, si debe realizar una combinación que solo conserve las claves de la izquierda o la derecha, pero no de ambas (IOW, realizando 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 Si las columnas clave tienen nombres diferentes, por ejemplo, left tiene keyLeft y right tiene keyRight en lugar de key , entonces deberá especificar left_on y right_on como 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 Al fusionar keyLeft desde left y keyRight desde right , si solo desea keyLeft o keyRight (pero no 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á que falta keyLeft . Puede averiguar qué columna mantener en función del índice del cuadro que se establece como clave. Esto puede ser importante cuando, por ejemplo, se realiza alguna operación OUTER JOIN.
DataFramesPor 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 3Si debe fusionar solo "new_val" (sin ninguna de las otras columnas), por lo general, solo puede crear subconjuntos de 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 UNIÓN EXTERNA IZQUIERDA, una solución de mayor rendimiento 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.0Como se mencionó, esto es similar, 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 Para unirse a más de una columna, especifique una lista para on (o left_on y 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'])merge*Fusionar un DataFrame con Series en el índice: consulte esta respuesta .
Además de merge , DataFrame.update y DataFrame.combine_first también se usan en ciertos casos para actualizar un DataFrame con otro.
pd.merge_ordered es una función útil para JOIN ordenados.
pd.merge_asof (léase: merge_asOf) es útil para uniones aproximadas .
Esta sección solo cubre los conceptos básicos y está diseñada solo para abrir el apetito. Para obtener más ejemplos y casos, consulte la documentación sobre merge , join y concat , así como los enlaces a las especificaciones de la función.
Vaya a otros temas en Pandas Merging 101 para continuar aprendiendo:
*Estás aquí.
Una vista visual complementaria de pd.concat([df0, df1], kwargs) . Tenga en cuenta que el significado de kwarg axis=0 o axis=1 no es tan intuitivo como df.mean() o df.apply(func)