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 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 merge
UNIÓ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 left
y right
que 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 left
se usan las claves de , y los datos que faltan right
se 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í, right
se usan claves de , y los datos que faltan left
se 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:
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 left
solo 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, left
tiene keyLeft
y right
tiene en keyRight
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
Evitar duplicar la columna clave en la salida
Al fusionar keyLeft
desde left
y keyRight
desde right
, si solo desea cualquiera de los dos ( keyLeft
o keyRight
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á keyLeft
que 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_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'])
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
, join
yconcat
así como los enlaces a las especificaciones de función.
Basado en índice * -JOIN (+ índice-columna merge
s)
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_on
si 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, left
se 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.join
qué valores predeterminados se unen en el índice. DataFrame.join
hace 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 lsuffix
y rsuffix
ya que de join
lo 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.concat
de @piRSquared .
Generalizando: merge
ing múltiples marcos de datos
A menudo, la situación surge cuando se combinan varios DataFrames. Ingenuamente, esto se puede hacer encadenando merge
llamadas:
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.concat
las uniones multidireccionales en claves únicas y DataFrame.join
las 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.concat
une 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
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 usarlo join
ya que puede manejar claves no únicas (tenga en cuenta que join
une DataFrames en su índice; llama merge
bajo 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
concat
ymerge
con un parámetro de dirección siendohorizontal
overtical
.axis=1
y quéaxis=0
es?merge
yconcat
y 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" es0
y cuál es1
.