Show code cell source
import os
# Por precaución, cambiamos el directorio activo de Python a aquel que contenga este notebook
if "PAD-book" in os.listdir():
os.chdir(r"PAD-book/Laboratorio-Computacional-de-Analytics/S5 - Extraer, transformar y cargar datos/S5.TU2/")
Unir bases de datos utilizando pandas
#
La información para analizar un problema no siempre se encuentra toda en un mismo archivo. Por lo anterior, es necesario unir la información disponible de múltiples fuentes en una misma base de datos. A continuación, expondremos los métodos disponibles en pandas
para llevar a cabo esa tarea.
Requisitos#
Para desarrollar este tutorial necesitarás:
Conocer las principales características de los arreglos en
numpy
y de losDataFrame
depandas
.Importar datos a un
DataFrame
desde distintos formatos.Indexar un
DataFrame
a partir de una o más columnas.
Objetivos#
Al final de este tutorial podrás:
1. Agregar columnas de un DataFrame
a otro DataFrame
.
2. Agregar filas de un DataFrame
a otro DataFrame
.
3. Unir dos DataFrame
de forma más flexible por coincidencia de filas o columnas.
1. Unir bases de datos#
Unir bases de datos significa consolidar la información existente en dos o más bases de datos de acuerdo con la coincidencia, bien sea de sus columnas, o de sus filas.
1.1. Unir bases de datos por coincidencia de filas#
Estos métodos agregan a un DataFrame
las columnas de otro según coincidan las filas en los dos.
Método join
#
Agrega a un DataFrame
las columnas de otro según coincidan los indices en los dos. Puede usarse una columna en lugar de su índice para el DataFrame
que llama al método.
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
A continuación una explicación de los parámetros.
other
: elDataFrame
a unir.on
: permite usar una o varias columnas delDataFrame
que llama al método para encontrar las coincidencias. De no especificarla, se encuentran las coincidencias en los índices.how
: es"left"
por defecto.how="left"
: elDataFrame
resultante tendrá el mismo número de filas que elDataFrame
que llama al método, ya que se usan solo las coincidencias con el índice o columna de esteDataframe
.how="right"
: elDataFrame
resultante tendrá el mismo número de filas que elDataFrame
entra por parámetro, ya que se usan solo las coincidencias con el índice o columna de esteDataframe
.how="outer"
: elDataFrame
resultante tendrá todas las filas de ambosDataFrame
, ya que se aceptan todas las coincidencias y no coincidencias de ambosDataFrame
.how="inner"
: elDataFrame
resultante solo tendrá los índices que existan en ambosDataFrame
.
lsufix
: si hay una o más columnas que tienen el mismo nombre en ambosDataFrame
, se le puede asignar un sufijo a las columnas delDataFrame
que llama al método para así diferenciarlas de las columnas del otroDataFrame
.rsuffix
: si hay una o más columnas que tienen el mismo nombre en ambosDataFrame
, se les puede asignar un sufijo a las columnas delDataFrame
que entra por parámetro para así diferenciarlas de las columnas delDataFrame
que llama al método.sort
: esFalse
por defecto.sort=True
: asigna un orden lexicográfico a las filas delDataFrame
resultante.sort=False
: preserva el orden en el que aparecen las filas de losDataFrame
originales.
Método merge
#
Agrega a un DataFrame
las columnas de otro según coincidan los indices en los dos. Puede usarse una columna en lugar de su índice para ambos DataFrame
. En este sentido, merge
es más flexible que join
, puesto que permite usar las coincidencias con las columnas del otro DataFrame
.
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False,
right_index=False, sort=False, suffixes=('_x', '_y'), indicator=False)
Al escoger la coincidencia de columnas. Si el DataDrame
que llama el método tiene \(n\) filas y el DataFrame
por parámetro tiene \(m\) filas, el DataFrame
resultante tendrá \(n+m\) filas. A continuación una explicación de los parámetros. El resultado aplica también para la coincidencia de filas, sumándose las columnas.
A continuación una explicación de los parámetros.
right
: elDataFrame
a unir.how
: se tienen las mismas opciones que con el métodojoin
:"left"
,"right"
,"outer"
e"inner"
.on
: nombre de una columna que se encuentre en ambosDataFrame
para identificar las coincidencias de la unión. Alternativamente pueden usarse los parámetrosleft_on
(oleft_index
) yright_on
(oright_index
).left_on
: nombres de las columnas delDataFrame
que llama al método, utilizadas para identificar las coincidencias.right_on
: nombres de las columnas delDataFrame
que entra por parámetro, utilizadas para identificar las coincidencias.left_index
: esFalse
por defecto.left_index=True
: especifica que se usa el índice delDataFrame
que llama al método, para identificar las coincidencias.left_index=False
: toma las columnas especificadas enon
o enleft_on
.
right_index
: esFalse
por defecto.right_index=True
: especifica que se usa el índice delDataFrame
que entra por parámetro, para identificar las coincidencias.right_index=False
: toma las columnas especificadas enon
o enright_on
.
sort
: esFalse
por defecto.sort=True
: asigna un orden lexicográfico a las filas delDataFrame
resultante.sort=False
: preserva el orden en el que aparecen las filas de losDataFrame
originales.
suffixes
: recibe una tupla de dos posiciones con los sufijos que se usarán para distinguir en caso de que existan columnas de nombre repetido.indicator
: agrega una columna que indica elDataFrame
del cual proviene la fila.
Uniones uno a uno#
Recordemos que la llave de una base de datos es una columna cuyos registros no se repiten. Podemos usar esta llave para indexar nuestro DataFrame
y este puede estar compuesto por una o más columnas.
La unión uno a uno se hace entre dos bases de datos de acuerdo con las coincidencias entre las llaves de ambas. Se entiende como una unión uno a uno, ya que en ambas bases de datos las llaves deben ser únicas y por lo tanto no existen coincidencias repetidas.
Importamos el paquete pandas
.
import pandas as pd
Ejemplo 1#
Consideremos los siguientes DataFrame
.
df = pd.DataFrame([[1, 2],
[3, 4],
[1, 2]],
columns=["A", "B"])
df2 = pd.DataFrame([[3, 2, 4],
[3, 4, 1]],
columns=["C", "D", "E"])
Debemos agregar a df
las columnas de df2
según coincidencia de índices uno a uno, preservando todas solo las filas que coinciden en df
y df2
.
Utilicemos el método merge
, especificando que la unión será por coincidencias interiores (que suceden en ambos) y activando las opciones de left_index
y right_index
.
df3 = df.merge(df2, how='inner', left_index=True, right_index=True)
df3
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 2 | 4 |
1 | 3 | 4 | 3 | 4 | 1 |
Alternativamente, podemos utilizar el método join
. Con este solo necesitamos dos argumentos, puesto que por defecto se usa el índice para la coincidencia de filas de los DataFrame
.
df3 = df.join(df2, how = 'inner')
df3
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 2 | 4 |
1 | 3 | 4 | 3 | 4 | 1 |
Uniones uno a \(n\)#
La unión uno a \(n\) se hace entre dos bases de datos de acuerdo con las coincidencias entre la llave de la primera y una columna cualquiera de la segunda (esta columna puede contener valores repetidos). Se entiende como una unión uno a \(n\), ya que para cada registro de la llave de la primera base de datos pueden existir hasta \(n\) coincidencias en la segunda.
Ejemplo 2#
Consideremos los siquientes DataFrame
.
df = pd.DataFrame([["Juan", "Contabilidad", 2100],
["Ignacio", "Ingeniería", 2000],
["Andrea", "Ingeniería", 2000]],
columns = ["Empleado", "Equipo", "Salario"])
df2 = pd.DataFrame([["Ingeniería", "Alex" ],
["Contabilidad", "Antonia"]],
columns = ["Equipo", "Supervisor"])
Debemos agregar a df
las columnas de df2
según coincidencia de índices uno a \(n\), preservar todas las filas de df
y solo las filas que coinciden de df2
.
Utilicemos el método merge
, especificando que la unión será por coincidencias interiores (que suceden en ambos), y que la columna "Equipo"
existe en ambos DataFrame
.
df3 = df.merge(df2, how = "inner", on = "Equipo")
df3
Empleado | Equipo | Salario | Supervisor | |
---|---|---|---|---|
0 | Juan | Contabilidad | 2100 | Antonia |
1 | Ignacio | Ingeniería | 2000 | Alex |
2 | Andrea | Ingeniería | 2000 | Alex |
Habriamos podido especificar cuál columna usar en cada DataFrame
, pero esto no fue necesario puesto que las columnas tienen el mismo nombre.
df3 = df.merge(df2, how = "inner", left_on = "Equipo", right_on = "Equipo")
df3
Empleado | Equipo | Salario | Supervisor | |
---|---|---|---|---|
0 | Juan | Contabilidad | 2100 | Antonia |
1 | Ignacio | Ingeniería | 2000 | Alex |
2 | Andrea | Ingeniería | 2000 | Alex |
Si quisieramos usar el método join
debemos indexar el segundo DataFrame
según su columna con la que evaluamos las coincidencias.
df2 = df2.set_index("Equipo")
df3 = df.join(df2, how = "inner", on = "Equipo")
df3
Empleado | Equipo | Salario | Supervisor | |
---|---|---|---|---|
0 | Juan | Contabilidad | 2100 | Antonia |
1 | Ignacio | Ingeniería | 2000 | Alex |
2 | Andrea | Ingeniería | 2000 | Alex |
Uniones \(n\) a uno#
Es equivalente a una unión uno a \(n\), donde la columna seleccionada para las coincidencias de la primera base de datos puede tener valores repetidos y las coincidencias con la segunda base de datos se evalúan utilizando su llave.
Uniones \(n\) a \(n\)#
La unión \(n\) a \(n\) se hace entre dos bases de datos de acuerdo con las coincidencias entre una columna (o grupo de columnas) de la primera y una columna (o grupo de columnas) de la segunda. Se entiende como una unión \(n\) a \(n\), ya que para cada registro (repetido o no) de la primera base de datos pueden existir hasta \(n\) coincidencias en la segunda. No es relevante que en una o en otra se evalúe la coincidencia de una llave.
Es importante mencionar que este tipo de unión es poco común y en ocasiones hasta desaconsejado por algunos programas especializados en manejo de datos (Stata, 2013).
Ejemplo 3#
Consideramos los siguientes DataFrame
.
df = pd.DataFrame([["Juan", "Tennis" ],
["Ignacio", "Tennis" ],
["Andrea", "Baloncesto"]],
columns = ["Alex", "Deporte"])
df2 = pd.DataFrame([["Tennis", "Raquetas"],
["Tennis", "Pelotas" ],
["Baloncesto", "Balón" ],
["Baloncesto", "Red" ],
["Natación", "Piscina" ]],
columns = ["Deporte", "Implemento"])
Debemos unir los DataFrame
de la celda de código en una relación \(n\) a \(n\) entre las columnas "Deporte"
. Además debemos emplear todas las coincidencias.
Debemos agregar a df
las columnas de df2
según coincidencia de índices \(n\) a \(n\), preservar todas las filas de df
y todas las filas de df2
.
Utilizamos el método merge
:
df3 = df.merge(df2, how = "outer", on = "Deporte")
df3
Alex | Deporte | Implemento | |
---|---|---|---|
0 | Juan | Tennis | Raquetas |
1 | Juan | Tennis | Pelotas |
2 | Ignacio | Tennis | Raquetas |
3 | Ignacio | Tennis | Pelotas |
4 | Andrea | Baloncesto | Balón |
5 | Andrea | Baloncesto | Red |
6 | NaN | Natación | Piscina |
Declaramos "Deporte"
como el índice para poder utilizar el método join
.
df2 = df2.set_index("Deporte")
df3 = df.join(df2, how = "outer", on = "Deporte")
df3
Alex | Deporte | Implemento | |
---|---|---|---|
0.0 | Juan | Tennis | Raquetas |
0.0 | Juan | Tennis | Pelotas |
1.0 | Ignacio | Tennis | Raquetas |
1.0 | Ignacio | Tennis | Pelotas |
2.0 | Andrea | Baloncesto | Balón |
2.0 | Andrea | Baloncesto | Red |
NaN | NaN | Natación | Piscina |
1.2 Unir bases de datos por coincidencia de filas o columnas#
Método concat
#
Agrega por coincidencia de filas o columnas (no ambas al tiempo) y permite flexibilidad para nombrar los índices y las columnas.
concat(objs, axis=0, join='outer', ignore_index=False, keys=None, sort=False)
objs
: en este caso no hay unDataFrame
que llame al método. Para este argumento debe incluirse una lista con dos o másDataFrame
para unir.axis
: es0
por defecto.axis=0
: define la unión de losDataFrame
por coincidencia de filas.axis=1
: define la unión de losDataFrame
por coincidencia de columnas.
join
: es"outer"
por defecto.join="inner"
: permite únicamente permite coincidencias mutuas.join="outer"
: permite la totalidad de las filas de ambos.
ignore_index
: esFalse
por defecto.ignore_index=True
: la base de datos resultante no tendrá en cuenta los índices de ninguno de los dosDataFrame
y asignará un índice numérico.ignore_index=False
: el índice de la base de datos resultante conserva los índices de los dosDataFrame
originales.
keys
: con el objetivo de conservar las columnas o los índices de ambas bases de datos se le puede asignar una llave por cadaDataFrame
, de tal manera que se pueda construir un índice múltiple o columnas múltiple. Los índices y columnas pasan de ser sencillos a representarse con tuplas.sort
: esFalse
por defecto.sort=True
: asigna un orden lexicográfico a las filas o columnas delDataFrame
resultante.sort=False
: preserva el orden en el que aparecen las filas o columnas de losDataFrame
originales.
Ejemplo 4#
Consideramos los siguientes DataFrame
.
df = pd.DataFrame([[1, 2],
[3, 4],
[1, 3]],
columns=['A', 'B'])
df2 = pd.DataFrame([[3, 2, 4],
[3, 4, 6],
[1, 0, 1]],
columns=['B', 'C', 'E'])
Debemos unir los DataFrame
por coincidencia de columnas y crear un índice múltiple (de tipo tupla) para diferenciar la información proveniente de cada uno de ellos.
df3 = pd.concat([df,df2], keys=['d1', 'd2'], sort=True)
df3
A | B | C | E | ||
---|---|---|---|---|---|
d1 | 0 | 1.0 | 2 | NaN | NaN |
1 | 3.0 | 4 | NaN | NaN | |
2 | 1.0 | 3 | NaN | NaN | |
d2 | 0 | NaN | 3 | 2.0 | 4.0 |
1 | NaN | 3 | 4.0 | 6.0 | |
2 | NaN | 1 | 0.0 | 1.0 |
El índice del DataFrame
está compuesto por tuplas, y no por valores sencillos como en los DataFrame
vistos anteriormente.
df3.index
MultiIndex([('d1', 0),
('d1', 1),
('d1', 2),
('d2', 0),
('d2', 1),
('d2', 2)],
)
Ahora, uniremos los DataFrame
por coincidencia de filas y crearemos un índice múltiple (de tipo tupla) para diferenciar la información proveniente de cada uno de ellos.
df4 = pd.concat([df,df2], axis=1, keys=['d1', 'd2'], sort=True)
df4
d1 | d2 | ||||
---|---|---|---|---|---|
A | B | B | C | E | |
0 | 1 | 2 | 3 | 2 | 4 |
1 | 3 | 4 | 3 | 4 | 6 |
2 | 1 | 3 | 1 | 0 | 1 |
Las columnas del DataFrame
están compuestas por tuplas, y no por valores sencillos como en los DataFrame
vistos anteriormente.
df4.columns
MultiIndex([('d1', 'A'),
('d1', 'B'),
('d2', 'B'),
('d2', 'C'),
('d2', 'E')],
)
Referencias#
Python (2020). Documentación sobre datetime
. Recuperado el 14 de diciembre de 2020 de:
https://docs.python.org/es/3/library/datetime.html
Stata (2013). Documentación sobre Merge. Recuperado el 14 de diciembre de 2020 de: https://www.stata.com/manuals13/dmerge.pdf
J. VanderPlas (2016) Python Data Science Handbook: Essential Tools for Working with Data O’Reilly Media, Inc.
Créditos#
Autores: Jorge Esteban Camargo Forero, Alejandro Mantilla Redondo, Diego Alejandro Cely Gomez
Fecha última actualización: 31/08/2022