Joins

Introducción

Es raro que un análisis de datos involucre un único dataframe. Lo habitual es que tengas muchos dataframes y que debas unirlos (join) para responder a las preguntas que te interesan.

pandas tiene un conjunto muy completo de opciones para combinar uno o más dataframes, y las dos más importantes son concatenate y merge. Algunos de los ejemplos de este capítulo te muestran cómo unir un par de dataframes. Por suerte, esto es suficiente, ya que puedes combinar tres dataframes combinando dos pares.

Requisitos previos

Este capítulo usará el paquete de análisis de datos pandas.

Concatenar

Si tienes dos o más dataframes con el mismo índice o las mismas columnas, puedes pegarlos en un único dataframe usando pd.concat().

Para las mismas columnas, pasa axis=0 para pegar los índices; para el mismo índice, pasa axis=1 para pegar las columnas. La función de concatenación normalmente se usará sobre una lista de dataframes.

Si quieres saber de dónde provienen los datos originales en el dataframe final, usa el argumento keys.

Aquí tienes un ejemplo con datos de la población de dos estados distintos que también usa la opción keys:

import pandas as pd

base_url = (
    "https://github.com/aeturrell/coding-for-economists/raw/refs/heads/main/data/"
)
state_codes = ["ca", "il"]
end_url = "pop.dta"

# This grabs the two dataframes, one for each state
list_of_state_dfs = [pd.read_stata(base_url + state + end_url) for state in state_codes]
# Show example of first entry in list of dataframes
print(list_of_state_dfs[0])

# Concatenate the list of dataframes
df = pd.concat(list_of_state_dfs, keys=state_codes, axis=0)
df
        county      pop
0  Los Angeles  9878554
1       Orange  2997033
2      Ventura   798364
county pop
ca 0 Los Angeles 9878554
1 Orange 2997033
2 Ventura 798364
il 0 Cook 5285107
1 DeKalb 103729
2 Will 673586

Observa que el argumento keys es opcional, pero resulta útil para saber de qué dataframe de origen proviene cada fila dentro del dataframe combinado.

TipEjercicio

Concatena los dos dataframes siguientes:

df1 = pd.DataFrame([['a', 1], ['b', 2]],
                   columns=['letter', 'number'])

df2 = pd.DataFrame([['c', 3], ['d', 4]],
                   columns=['letter', 'number'])

Merge

Hay tantas opciones para combinar dataframes con pd.merge(left, right, on=..., how=... que no podremos cubrirlas todas aquí. Las características más importantes son: los dos dataframes que se van a combinar, sobre qué variables (también llamadas claves) se hace el merge (que pueden ser índices) mediante on=, y cómo hacer el merge (por ejemplo, left, right, outer, inner) mediante how=. Este diagrama muestra un ejemplo de merge usando las claves del dataframe de la izquierda:

El argumento how= funciona de las siguientes maneras: - how='left' usa solo las claves del dataframe de la izquierda para el merge. - how='right' usa solo las claves del dataframe de la derecha para el merge. - how='inner' usa las claves que aparecen en ambos dataframes para el merge. - how='outer' usa el producto cartesiano de las claves de ambos dataframes para el merge.

Veamos ejemplos de algunos de ellos:

left = pd.DataFrame(
    {
        "key1": ["K0", "K0", "K1", "K2"],
        "key2": ["K0", "K1", "K0", "K1"],
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
    }
)
right = pd.DataFrame(
    {
        "key1": ["K0", "K1", "K1", "K2"],
        "key2": ["K0", "K0", "K0", "K0"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    }
)
# Right merge
pd.merge(left, right, on=["key1", "key2"], how="right")
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
3 K2 K0 NaN NaN C3 D3

Observa que la combinación de claves K2 y K0 no existía en el dataframe de la izquierda, por lo que sus entradas en el dataframe final son NaN. Pero sí tiene entradas porque elegimos las claves del dataframe de la derecha.

¿Y un merge interno (inner)?

pd.merge(left, right, on=["key1", "key2"], how="inner")
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2

Ahora vemos que la combinación K2 y K0 queda excluida porque no existía en la intersección de claves de ambos dataframes.

Por último, veamos un merge externo (outer) que incluye información adicional mediante el argumento indicator:

pd.merge(left, right, on=["key1", "key2"], how="outer", indicator=True)
key1 key2 A B C D _merge
0 K0 K0 A0 B0 C0 D0 both
1 K0 K1 A1 B1 NaN NaN left_only
2 K1 K0 A2 B2 C1 D1 both
3 K1 K0 A2 B2 C2 D2 both
4 K2 K0 NaN NaN C3 D3 right_only
5 K2 K1 A3 B3 NaN NaN left_only

Ahora podemos ver que están aquí los productos de todas las combinaciones de claves. La opción indicator=True ha hecho que se añada una columna extra, llamada ’_merge’, que nos indica de qué dataframe provienen las claves de esa fila.

TipExercise

Combina los siguientes dos dataframes usando los argumentos left_on y right_on para especificar un join sobre lkey y rkey, respectivamente:

df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [1, 2, 3, 5]})
df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [5, 6, 7, 8]})
TipExercise

Combina los siguientes dos dataframes sobre "a" usando how="left" como argumento:

df1 = pd.DataFrame({'a': ['foo', 'bar'], 'b': [1, 2]})
df2 = pd.DataFrame({'a': ['foo', 'baz'], 'c': [3, 4]})

¿Qué observas en la posición .loc[1, "c"] del dataframe combinado?

Para más información sobre las opciones de merge, consulta la completa documentación sobre merging de pandas.