Introducción
Contenido
Pandas proporciona una amplia gama de métodos y funciones para manipular datos, incluida la fusión de DataFrames. Fusionar DataFrames le permite crear un nuevo DataFrame sin modificar la fuente de datos original o alterar la fuente de datos original.
Si está familiarizado con SQL o un tipo similar de datos tabulares, probablemente esté familiarizado con el término join
, lo que significa combinar DataFrames para formar un nuevo DataFrame. Si eres un principiante, puede ser difícil comprender completamente los tipos de unión (interna, externa, izquierda, derecha). En este tutorial repasaremos los tipos de combinación con ejemplos.
Nuestro enfoque principal sería el uso de merge()
y concat()
funciones. Sin embargo, discutiremos otros métodos de fusión para brindarle tantas alternativas prácticas como sea posible.
Para este tutorial, usamos Pandas versión 1.1.4 y NumPy versión 1.19.4.
Para su comodidad, aquí está la tabla de contenido:
- Fusionar DataFrames usando merge ()
- Fusionar DataFrames usando join ()
- Combinar DataFrames usando append ()
- Fusionar DataFrames usando concat ()
- Fusionar DataFrames usando combine_first () y update ()
Fusionar DataFrames usando merge ()
Comencemos por configurar nuestros DataFrames, que usaremos para el resto del tutorial.
df1
incluirá nuestra lista de usuarios imaginaria con nombres, correos electrónicos e ID.
import pandas as pd
df1 = pd.DataFrame({'user_id': ['id001', 'id002', 'id003', 'id004', 'id005', 'id006', 'id007'],
'first_name': ['Rivi', 'Wynnie', 'Kristos', 'Madalyn', 'Tobe', 'Regan', 'Kristin'],
'last_name': ['Valti', 'McMurty', 'Ivanets', 'Max', 'Riddich', 'Huyghe', 'Illis'],
'email': ['[email protected]', '[email protected]', '[email protected]',
'[email protected]', '[email protected]', '[email protected]', '[email protected]']
})
Al diseñar bases de datos, se considera una buena práctica mantener la configuración del perfil (como el color de fondo, el enlace de la imagen del avatar, el tamaño de fuente, etc.) en una tabla separada de los datos del usuario (correo electrónico, fecha de adición, etc.) Estas tablas pueden tener una relación de uno a uno.
Para simular este escenario haremos lo mismo creando df2
con URL de imagen e ID de usuario:
df2 = pd.DataFrame({'user_id': ['id001', 'id002', 'id003', 'id004', 'id005'],
'image_url': ['http://example.com/img/id001.png', 'http://example.com/img/id002.jpg',
'http://example.com/img/id003.bmp', 'http://example.com/img/id004.jpg',
'http://example.com/img/id005.png']
})
Así es como se ven nuestros DataFrames:
# df1
user_id first_name last_name email
0 id001 Rivi Valti [email protected]
1 id002 Wynnie McMurty [email protected]
2 id003 Kristos Ivanets [email protected]
3 id004 Madalyn Max [email protected]
4 id005 Tobe Riddich [email protected]
5 id006 Regan Huyghe [email protected]
6 id007 Kristin Illis [email protected]
#df2
user_id image_url
0 id001 http://example.com/img/id001.png
1 id002 http://example.com/img/id002.jpg
2 id003 http://example.com/img/id003.bmp
3 id004 http://example.com/img/id004.jpg
4 id005 http://example.com/img/id005.png
Combinemos estos DataFrames con el merge()
función. Primero, eche un vistazo a todas las opciones que esta función puede aceptar de un vistazo:
pd.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,
validate=None)
La mayoría de estas opciones tienen un valor predeterminado, excepto el izquierda y derecho. Estos dos parámetros son los nombres de los DataFrames que fusionaremos. La función en sí devolverá un nuevo DataFrame, que almacenaremos en df3_merged
variable.
Ingresa el siguiente código en tu shell de Python:
df3_merged = pd.merge(df1, df2)
Dado que nuestros dos DataFrames tienen la columna user_id
con el mismo nombre, el merge()
La función une automáticamente dos tablas que coinciden con esa clave. Si tuviéramos dos columnas con diferentes nombres, podríamos usar left_on='left_column_name'
y right_on='right_column_name'
para especificar claves en ambos DataFrames explícitamente.
Vamos a imprimir el df3_merged
variable para ver su contenido:
user_id first_name last_name email image_url
0 id001 Rivi Valti [email protected] http://example.com/img/id001.png
1 id002 Wynnie McMurty [email protected] http://example.com/img/id002.jpg
2 id003 Kristos Ivanets [email protected] http://example.com/img/id003.bmp
3 id004 Madalyn Max [email protected] http://example.com/img/id004.jpg
4 id005 Tobe Riddich [email protected] http://example.com/img/id005.png
Notarás que df3_merged
tiene solo 5 filas, mientras que el df1 original tenía 7. ¿Por qué?
Cuando el valor predeterminado de la how
el parámetro está establecido en inner
, se genera un nuevo DataFrame a partir de la intersección de los DataFrames izquierdo y derecho. Por lo tanto, si un user_id
falta en una de las tablas, no estaría en el DataFrame combinado.
Esto seguiría siendo cierto incluso si se intercambiaran los lugares de las filas izquierda y derecha:
df3_merged = pd.merge(df2, df1)
Los resultados siguen siendo:
user_id image_url first_name last_name email
0 id001 http://example.com/img/id001.png Rivi Valti [email protected]
1 id002 http://example.com/img/id002.jpg Wynnie McMurty [email protected]
2 id003 http://example.com/img/id003.bmp Kristos Ivanets [email protected]
3 id004 http://example.com/img/id004.jpg Madalyn Max [email protected]
4 id005 http://example.com/img/id005.png Tobe Riddich [email protected]
Usuarios con ID 'id006'
y 'id007'
no forman parte de los DataFrames fusionados ya que no se cruzan en ambas tablas.
Sin embargo, hay ocasiones en las que queremos usar uno de los DataFrame como el DataFrame principal e incluir todas las filas incluso si no todas se cruzan entre sí. Es decir, tener todos nuestros usuarios, mientras que el image_url
es opcional.
¿Cómo? Mediante el uso merge()
, podemos pasar el 'left'
argumento a la how
parámetro:
df_left_merge = pd.merge(df1, df2, how='left')
print(df_left_merge)
Con una combinación izquierda, hemos incluido todos los elementos del DataFrame izquierdo (df1
) y todos los elementos del DataFrame correcto (df2
). Ejecutar el código anterior mostraría esto:
user_id first_name last_name email image_url
0 id001 Rivi Valti [email protected] http://example.com/img/id001.png
1 id002 Wynnie McMurty [email protected] http://example.com/img/id002.jpg
2 id003 Kristos Ivanets [email protected] http://example.com/img/id003.bmp
3 id004 Madalyn Max [email protected] http://example.com/img/id004.jpg
4 id005 Tobe Riddich [email protected] http://example.com/img/id005.png
5 id006 Regan Huyghe [email protected] NaN
6 id007 Kristin Illis [email protected] NaN
Las celdas que no tienen ningún valor coincidente con el DataFrame izquierdo se rellenan con NaN
.
¿Por qué no intentamos una combinación correcta? Cree el siguiente DataFrame combinado:
df_right_merge = pd.merge(df1, df2, how='right')
print(df_right_merge)
Como era de esperar, la combinación derecha devolvería todos los valores del DataFrame izquierdo que coincida con el DataFrame derecho:
user_id first_name last_name email image_url
0 id001 Rivi Valti [email protected] http://example.com/img/id001.png
1 id002 Wynnie McMurty [email protected] http://example.com/img/id002.jpg
2 id003 Kristos Ivanets [email protected] http://example.com/img/id003.bmp
3 id004 Madalyn Max [email protected] http://example.com/img/id004.jpg
4 id005 Tobe Riddich [email protected] http://example.com/img/id005.png
Como cada fila en df2
tiene un valor en df1
, esta right
unirse es similar a la inner
unirse, en este caso.
Echemos un vistazo a outer
Uniones. Para ilustrar mejor cómo funcionan, intercambiemos lugares de nuestros DataFrames y creemos 2 nuevas variables para las uniones izquierdas y externas:
df_left = pd.merge(df2, df1, how='left', indicator=True)
df_outer = pd.merge(df2, df1, how='outer', indicator=True)
print(df_left)
print(df_outer)
Tenga en cuenta que nuestro DataFrame izquierdo es df2
y el DataFrame correcto es df1
. Utilizando how='outer'
fusiona DataFrames que coinciden con la clave, pero también incluye los valores que faltan o no coinciden.
También agregamos el indicator
bandera y ponerlo en True
para que Pandas agregue una columna adicional _merge
hasta el final de nuestro DataFrame. Esta columna nos dice si se encontró una fila en el DataFrames izquierdo, derecho o en ambos.
los df_left
variable se ve así:
user_id image_url first_name last_name email _merge
0 id001 http://example.com/img/id001.png Rivi Valti [email protected] both
1 id002 http://example.com/img/id002.jpg Wynnie McMurty [email protected] both
2 id003 http://example.com/img/id003.bmp Kristos Ivanets [email protected] both
3 id004 http://example.com/img/id004.jpg Madalyn Max [email protected] both
4 id005 http://example.com/img/id005.png Tobe Riddich [email protected] both
Sin embargo, df_outer
tiene estos datos:
user_id image_url first_name last_name email _merge
0 id001 http://example.com/img/id001.png Rivi Valti [email protected] both
1 id002 http://example.com/img/id002.jpg Wynnie McMurty [email protected] both
2 id003 http://example.com/img/id003.bmp Kristos Ivanets [email protected] both
3 id004 http://example.com/img/id004.jpg Madalyn Max [email protected] both
4 id005 http://example.com/img/id005.png Tobe Riddich [email protected] both
5 id006 NaN Regan Huyghe [email protected] right_only
6 id007 NaN Kristin Illis [email protected] right_only
Note que en el df_outer
Marco de datos id006
y id007
solo existe en el DataFrame derecho (en este caso es df1
). Si intentáramos comparar las uniones izquierdas y externas sin intercambiar los lugares, obtendríamos los mismos resultados para ambas.
Fusionar DataFrames usando join ()
diferente a merge()
que es un método de la instancia de Pandas, join()
es un método del propio DataFrame. Esto significa que podemos usarlo como un método estático en el DataFrame: DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
.
El DataFrame que llamamos join()
de será nuestro DataFrame izquierdo. El DataFrame en el other
El argumento sería nuestro DataFrame correcto.
los on
El parámetro puede tomar uno o más (['key1', 'key2' ...]
) argumentos para definir la clave coincidente, mientras que how
El parámetro toma uno de los argumentos del identificador (izquierdo, derecho, externo, interno) y se establece en left
por defecto.
Intentemos unirnos df2
a df1
:
df_join = df1.join(df2, rsuffix='_right')
print(df_join)
Como el merge()
función, la join()
La función intenta automáticamente hacer coincidir las claves (columnas) con el mismo nombre. En nuestro caso, es el user_id
llave.
El código anterior imprime esto:
user_id first_name last_name email user_id_right image_url
0 id001 Rivi Valti [email protected] id001 http://example.com/img/id001.png
1 id002 Wynnie McMurty [email protected] id002 http://example.com/img/id002.jpg
2 id003 Kristos Ivanets [email protected] id003 http://example.com/img/id003.bmp
3 id004 Madalyn Max [email protected] id004 http://example.com/img/id004.jpg
4 id005 Tobe Riddich [email protected] id005 http://example.com/img/id005.png
5 id006 Regan Huyghe [email protected] NaN NaN
6 id007 Kristin Illis [email protected] NaN NaN
Probablemente hayas notado una «columna duplicada» llamada user_id_right
. Si no desea mostrar esa columna, puede configurar el user_id
columnas como un índice en ambas columnas para que se unan sin un sufijo:
df_join_no_duplicates = df1.set_index('user_id').join(df2.set_index('user_id'))
print(df_join_no_duplicates)
Al hacerlo, nos estamos deshaciendo de la user_id
columna y configurándola como la columna de índice. Esto nos proporciona un DataFrame resultante más limpio:
first_name last_name email image_url
user_id
id001 Rivi Valti [email protected] http://example.com/img/id001.png
id002 Wynnie McMurty [email protected] http://example.com/img/id002.jpg
id003 Kristos Ivanets [email protected] http://example.com/img/id003.bmp
id004 Madalyn Max [email protected] http://example.com/img/id004.jpg
id005 Tobe Riddich [email protected] http://example.com/img/id005.png
id006 Regan Huyghe [email protected] NaN
id007 Kristin Illis [email protected] NaN
Combinar DataFrames usando append ()
Como apunta la documentación oficial de Pandas, desde concat()
y append()
Los métodos devuelven nuevas copias de DataFrames, el uso excesivo de estos métodos puede afectar el rendimiento de su programa.
Agregar es muy útil cuando desea fusionar dos DataFrames en el eje de fila únicamente. Esto significa que en lugar de hacer coincidir los datos en sus columnas, queremos un nuevo DataFrame que contenga todas las filas de 2 DataFrames.
Vamos a añadir df2
a df1
e imprime los resultados:
df_append = df1.append(df2, ignore_index=True)
print(df_append)
Utilizando append()
no coincidirá con DataFrames en ninguna clave. Simplemente agregará el otro DataFrame al primero y devolverá una copia del mismo. Si las formas de DataFrames no coinciden, Pandas reemplazará cualquier celda no coincidente con un NaN.
El resultado para agregar los dos DataFrames se ve así:
user_id first_name last_name email image_url
0 id001 Rivi Valti [email protected] NaN
1 id002 Wynnie McMurty [email protected] NaN
2 id003 Kristos Ivanets [email protected] NaN
3 id004 Madalyn Max [email protected] NaN
4 id005 Tobe Riddich [email protected] NaN
5 id006 Regan Huyghe [email protected] NaN
6 id007 Kristin Illis [email protected] NaN
7 id001 NaN NaN NaN http://example.com/img/id001.png
8 id002 NaN NaN NaN http://example.com/img/id002.jpg
9 id003 NaN NaN NaN http://example.com/img/id003.bmp
10 id004 NaN NaN NaN http://example.com/img/id004.jpg
11 id005 NaN NaN NaN http://example.com/img/id005.png
La mayoría de los usuarios eligen concat()
sobre el append()
ya que también proporciona la opción de eje y coincidencia de claves.
Fusionar DataFrames usando concat ()
La concatenación es un poco más flexible en comparación con merge()
y join()
ya que nos permite combinar DataFrames verticalmente (en filas) u horizontalmente (en columnas).
La compensación es que se descartarán los datos que no coincidan. Aquí está la función completa con los parámetros:
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None,
levels=None, names=None, verify_integrity=False, sort=False, copy=True)
A continuación, se muestran los parámetros más utilizados para concat()
función:
objs
es la lista de objetos DataFrame ([df1, df2, …]) para ser concatenadosaxis
define la dirección de la concatenación,0
para filas y1
para columnajoin
puede serinner
(intersección) oouter
(Unión)ignore_index
por defecto establecido enFalse
que permite que los valores de índice permanezcan como estaban en los DataFrames originales, puede causar valores de índice duplicados. Si se establece enTrue
, ignorará los valores originales y reasignará valores de índice en orden secuencialkeys
nos permite construir un índice jerárquico. Piense en ello como otro nivel del índice que se adjunta en la parte exterior izquierda del DataFrame que nos ayuda a distinguir los índices cuando los valores no son únicos.
Creemos un nuevo DataFrame con los mismos tipos de columna que el df2, pero este incluye el image_url
para id006
y id007
:
df2_addition = pd.DataFrame({'user_id': ['id006', 'id007'],
'image_url': ['http://example.com/img/id006.png',
'http://example.com/img/id007.jpg']
})
Para unirse df2
y df2_addition
por filas, podemos pasarlos en una lista como el objs
y asigne el DataFrame resultante a una nueva variable:
df_row_concat = pd.concat([df2, df2_addition])
print(df_row_concat)
Completamos con éxito los valores faltantes:
user_id image_url
0 id001 http://example.com/img/id001.png
1 id002 http://example.com/img/id002.jpg
2 id003 http://example.com/img/id003.bmp
3 id004 http://example.com/img/id004.jpg
4 id005 http://example.com/img/id005.png
0 id006 http://example.com/img/id006.png
1 id007 http://example.com/img/id007.jpg
Sin embargo, eche un vistazo a los índices de la columna más a la izquierda. Los índices 0
y 1
están repitiendo. Para obtener valores de índice completamente nuevos y únicos, pasamos True
al ignore_index
parámetro:
df_row_concat = pd.concat([df2, df2_addition], ignore_index=True)
Ahora nuestro df_row_concat
tiene valores de índice únicos:
user_id image_url
0 id001 http://example.com/img/id001.png
1 id002 http://example.com/img/id002.jpg
2 id003 http://example.com/img/id003.bmp
3 id004 http://example.com/img/id004.jpg
4 id005 http://example.com/img/id005.png
5 id006 http://example.com/img/id006.png
6 id007 http://example.com/img/id007.jpg
Como mencionamos anteriormente, la concatenación puede funcionar tanto horizontal como verticalmente. Para unir dos DataFrames juntos por columnas, necesitaremos cambiar el axis
valor del predeterminado 0
a 1
:
df_column_concat = pd.concat([df1, df_row_concat], axis=1)
print(df_column_concat)
Notará que no funciona como una combinación, haciendo coincidir dos tablas en una clave:
user_id first_name last_name email user_id image_url
0 id001 Rivi Valti [email protected] id001 http://example.com/img/id001.png
1 id002 Wynnie McMurty [email protected] id002 http://example.com/img/id002.jpg
2 id003 Kristos Ivanets [email protected] id003 http://example.com/img/id003.bmp
3 id004 Madalyn Max [email protected] id004 http://example.com/img/id004.jpg
4 id005 Tobe Riddich [email protected] id005 http://example.com/img/id005.png
5 id006 Regan Huyghe [email protected] id006 http://example.com/img/id006.png
6 id007 Kristin Illis [email protected] id007 http://example.com/img/id007.jpg
Si nuestro DataFrame correcto ni siquiera tuviera un user_id
columna, esta concatenación todavía devolvería el mismo resultado. los concat()
La función pega dos DataFrames juntos, teniendo en cuenta los valores de los índices de DataFrames y la forma de la tabla.
No hace coincidir claves como merge()
de join()
. Pruebe diferentes combinaciones de concatenación cambiando el join
parámetro para ver las diferencias!
Fusionar DataFrames usando combine_first () y update ()
En algunos casos, es posible que desee completar los datos que faltan en su DataFrame combinándolos con otro DataFrame. Al hacerlo, mantendrá todos los valores que no faltan en el primer DataFrame mientras reemplaza todos NaN
valores con valores disponibles no perdidos del segundo DataFrame (si hay alguno).
Para este ejemplo, importaremos NumPy para usar NaN
valores. Si instaló Pandas con pip
, NumPy ya debería estar instalado.
Escriba el siguiente código en su shell de Python o archivo de secuencia de comandos:
import numpy as np
df_first = pd.DataFrame({'COL 1': ['X', 'X', np.nan],
'COL 2': ['X', np.nan, 'X'],
'COL 3': [np.nan, 'X', 'X']},
index=range(0, 3))
df_second = pd.DataFrame({'COL 1': [np.nan, 'O', 'O'],
'COL 2': ['O', 'O', 'O']},
index=range(0, 3))
print(df_first)
print(df_second)
los df_first
DataFrame tiene 3 columnas y 3 valores faltantes en cada una de ellas:
COL 1 COL 2 COL 3
0 X X NaN
1 X NaN X
2 NaN X X
Mientras df_second
tiene solo 2 columnas y un valor faltante en la primera columna:
COL 1 COL 2
0 NaN O
1 O O
2 O O
Nosotros podemos usar df_second
para parchear los valores faltantes en df_first
con todos los valores correspondientes:
df_tictactoe = df_first.combine_first(df_second)
print(df_tictactoe)
Como se mencionó anteriormente, el uso de combine_first()
el método solo reemplazará NaN
valores en orden de índice, y dejará todos los valores no perdidos en el primer DataFrame como están:
COL 1 COL 2 COL 3
0 X X NaN
1 X O X
2 O X X
Por otro lado, si quisiéramos sobrescribir los valores en df_first
con los valores correspondientes de df_second
(independientemente de que sean NaN o no), usaríamos el update()
método.
Primero agreguemos otro DataFrame a nuestro código:
df_third = pd.DataFrame({'COL 1': ['O'], 'COL 2': ['O'], 'COL 3': ['O']})
print(df_third)
La forma es (1, 3) – 1 fila y tres columnas, excluyendo el índice:
COL 1 COL 2 COL 3
0 O O O
Ahora actualice el df_first
con los valores de df_third
:
df_first.update(df_third)
print(df_first)
Tenga en cuenta que a diferencia combine_first()
, update()
no devuelve un nuevo DataFrame. Modifica el df_first
in situ, alterando los valores correspondientes:
COL 1 COL 2 COL 3
0 O O O
1 X NaN X
2 NaN X X
los overwrite
parámetro de la update()
la función está configurada en True
por defecto. Es por eso que cambia todos los valores correspondientes, en lugar de solo NaN
valores. Podemos cambiarlo a False
para reemplazar solo NaN
valores:
df_tictactoe.update(df_first, overwrite=False)
print(df_tictactoe)
Aquí está el estado final de nuestro df_tictactoe
Marco de datos:
COL 1 COL 2 COL 3
0 X X O
1 X O X
2 O X X
¡No solo actualizamos con éxito los valores, sino que también ganamos el juego Tic-Tac-Toe!
Conclusión
Pandas proporciona herramientas poderosas para fusionar DataFrames. Pero puede ser difícil decidir cuándo usar qué. Mientras que la mayoría de las veces merge()
la función es suficiente, en algunos casos es posible que desee utilizar concat()
para fusionar filas o usar join()
con sufijos, o deshacerse de los valores perdidos con combine_first()
y update()
. Incluso puede agregar filas de datos con append()
.
Utilice la función con la que se sienta más cómodo y que sea mejor para la tarea en cuestión. ¿Cómo te ayudarían estas funciones a manipular datos en Pandas?