miad4.png

Hide 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 los DataFrame de pandas.

  • 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: el DataFrame a unir.

  • on: permite usar una o varias columnas del DataFrame 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": el DataFrame resultante tendrá el mismo número de filas que el DataFrame que llama al método, ya que se usan solo las coincidencias con el índice o columna de este Dataframe.

    • how="right": el DataFrame resultante tendrá el mismo número de filas que el DataFrame entra por parámetro, ya que se usan solo las coincidencias con el índice o columna de este Dataframe.

    • how="outer": el DataFrame resultante tendrá todas las filas de ambos DataFrame, ya que se aceptan todas las coincidencias y no coincidencias de ambos DataFrame.

    • how="inner": el DataFrame resultante solo tendrá los índices que existan en ambos DataFrame.

  • lsufix: si hay una o más columnas que tienen el mismo nombre en ambos DataFrame, se le puede asignar un sufijo a las columnas del DataFrame que llama al método para así diferenciarlas de las columnas del otro DataFrame.

  • rsuffix: si hay una o más columnas que tienen el mismo nombre en ambos DataFrame, se les puede asignar un sufijo a las columnas del DataFrame que entra por parámetro para así diferenciarlas de las columnas del DataFrame que llama al método.

  • sort: es False por defecto.

    • sort=True: asigna un orden lexicográfico a las filas del DataFrame resultante.

    • sort=False: preserva el orden en el que aparecen las filas de los DataFrame 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: el DataFrame a unir.

  • how: se tienen las mismas opciones que con el método join: "left", "right", "outer" e "inner".

  • on: nombre de una columna que se encuentre en ambos DataFrame para identificar las coincidencias de la unión. Alternativamente pueden usarse los parámetros left_on (o left_index) y right_on (o right_index).

  • left_on: nombres de las columnas del DataFrame que llama al método, utilizadas para identificar las coincidencias.

  • right_on: nombres de las columnas del DataFrame que entra por parámetro, utilizadas para identificar las coincidencias.

  • left_index: es False por defecto.

    • left_index=True: especifica que se usa el índice del DataFrame que llama al método, para identificar las coincidencias.

    • left_index=False: toma las columnas especificadas en on o en left_on.

  • right_index: es False por defecto.

    • right_index=True: especifica que se usa el índice del DataFrame que entra por parámetro, para identificar las coincidencias.

    • right_index=False: toma las columnas especificadas en on o en right_on.

  • sort: es False por defecto.

    • sort=True: asigna un orden lexicográfico a las filas del DataFrame resultante.

    • sort=False: preserva el orden en el que aparecen las filas de los DataFrame 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 el DataFrame 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 un DataFrame que llame al método. Para este argumento debe incluirse una lista con dos o más DataFrame para unir.

  • axis: es 0 por defecto.

    • axis=0: define la unión de los DataFrame por coincidencia de filas.

    • axis=1: define la unión de los DataFrame 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: es False por defecto.

    • ignore_index=True: la base de datos resultante no tendrá en cuenta los índices de ninguno de los dos DataFrame y asignará un índice numérico.

    • ignore_index=False: el índice de la base de datos resultante conserva los índices de los dos DataFrame originales.

  • keys: con el objetivo de conservar las columnas o los índices de ambas bases de datos se le puede asignar una llave por cada DataFrame, 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: es False por defecto.

    • sort=True: asigna un orden lexicográfico a las filas o columnas del DataFrame resultante.

    • sort=False: preserva el orden en el que aparecen las filas o columnas de los DataFrame 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