pandas: merge, join y concat
Los datos reales nunca viven en una sola tabla. Los clientes están en una tabla, las transacciones en otra, las sucursales en otra. Para analizar necesitás cruzar tablas — exactamente como los JOINs de SQL pero con la sintaxis de pandas. Si ya dominás SQL JOINs (lecciones SQL 07 y 08), esto te va a resultar familiar.
Concepto teórico
Las 3 operaciones de combinación
| Operación | Qué hace | Equivalente SQL | Cuándo usarla |
|---|---|---|---|
pd.merge() |
Combina por columna clave | JOIN ... ON |
Cruzar tablas por una clave compartida |
pd.concat() |
Apila filas o columnas | UNION ALL |
Combinar tablas con la misma estructura |
df.join() |
Combina por índice | JOIN ... ON index |
Cuando la clave es el índice |
pd.merge(). Es la operación más
versátil y explícita. concat() se usa cuando tenés datos partidos en archivos (ej: un CSV por mes)
y querés apilarlos. join() es un atajo para merge por índice que se usa menos frecuentemente.Los 4 tipos de merge (joins)
Igual que en SQL, pandas soporta 4 tipos de cruce. La diferencia es qué pasa con las filas que no tienen match en la otra tabla:
| Tipo | how= | Qué conserva | Filas sin match |
|---|---|---|---|
| Inner | "inner" |
Solo filas con match en ambas | Se pierden |
| Left | "left" |
Todas las de la izquierda | NaN en columnas de la derecha |
| Right | "right" |
Todas las de la derecha | NaN en columnas de la izquierda |
| Outer | "outer" |
Todas las de ambas | NaN donde no hay match |
# Sintaxis de merge
pd.merge(
df_izquierda,
df_derecha,
on="columna_clave", # Si se llama igual en ambas
# left_on="col_izq", # Si se llaman distinto
# right_on="col_der",
how="inner" # inner | left | right | outer
)
concat: apilar DataFrames
pd.concat() es para cuando tenés dos o más DataFrames con las mismas columnas y
querés unirlos verticalmente (apilar filas). El caso típico: un archivo CSV por mes y querés un solo DataFrame
con todo el año.
# Concatenar verticalmente (filas) pd.concat([df_enero, df_febrero, df_marzo], ignore_index=True) # Concatenar horizontalmente (columnas) → menos común pd.concat([df1, df2], axis=1)
ignore_index=True,
concat() conserva los índices originales de cada DataFrame. Esto significa que puedes terminar con
un DataFrame donde el índice dice 0, 1, 2, 0, 1, 2 (repetidos). Siempre usá ignore_index=True al
concatenar verticalmente.
cliente_id pero no tiene el nombre ni la
ciudad. La tabla de clientes tiene cliente_id con nombre, ciudad y segmento. Necesitás hacer
merge para cruzarlas. Esto pasa en cualquier empresa con base de datos relacional.
Ejemplos explicados paso a paso
Ejemplo 1: merge INNER — el cruce básico
Cruzar transacciones con datos del cliente. Solo se conservan las filas que tienen match en ambas tablas.
Hacé clic en ▶ Ejecutar
Ejemplo 2: LEFT merge — conservar todos los de la izquierda
El caso más común: querés TODAS las transacciones, incluso las que no tienen match en clientes. Las sin match muestran NaN.
Hacé clic en ▶ Ejecutar
Ejemplo 3: OUTER merge y merge con claves distintas
A veces la columna clave se llama distinto en cada tabla. Usá left_on y right_on.
Hacé clic en ▶ Ejecutar
indicator=True al merge y
pandas crea una columna _merge que dice "both", "left_only" o
"right_only" para cada fila. Es perfecto para diagnosticar cuántas filas tienen match y cuántas no.
Ejemplo 4: concat para apilar DataFrames
Cuando los datos vienen partidos (un CSV por mes, un archivo por región), se concatenan para formar un solo DataFrame.
Hacé clic en ▶ Ejecutar
Ejemplo 5: Merge múltiple — enriquecer datos paso a paso
En un caso real, cruzás más de 2 tablas. Hacés un merge tras otro, enriqueciendo tu dataset progresivamente.
Hacé clic en ▶ Ejecutar
len() antes y después del merge.Referencia rápida
| Operación | Sintaxis | Uso |
|---|---|---|
| Inner merge | pd.merge(a, b, on="key") |
Solo filas con match |
| Left merge | pd.merge(a, b, on="key", how="left") |
Todas las de la tabla izquierda |
| Right merge | pd.merge(a, b, on="key", how="right") |
Todas las de la tabla derecha |
| Outer merge | pd.merge(a, b, on="key", how="outer") |
Todas las de ambas |
| Claves distintas | left_on="x", right_on="y" |
Columnas con distinto nombre |
| Diagnóstico | indicator=True |
Columna _merge con both/left/right |
| Concat vertical | pd.concat([dfs], ignore_index=True) |
Apilar filas |
| Concat horizontal | pd.concat([dfs], axis=1) |
Agregar columnas lado a lado |
Ejercicios
Ejercicio 1: Inner merge simple
Cruzá la tabla de pedidos con la de productos usando Prod_ID. Imprimí el resultado. Debe incluir
Notebook.
Hacé clic en ▶ Ejecutar
Ejercicio 2: Left merge
Hacé un LEFT merge de pedidos con productos. Imprimí el resultado — deben aparecer las 3 filas de pedidos (la
última con NaN). Debe incluir NaN o nan.
Hacé clic en ▶ Ejecutar
Ejercicio 3: concat vertical
Concatená dos DataFrames de ventas (enero y febrero) verticalmente con ignore_index=True.
Imprimí la cantidad total de filas. Debe dar 6.
Hacé clic en ▶ Ejecutar
Ejercicio 4: Merge con claves distintas
Las tablas tienen la clave con distinto nombre (cod_cli vs ID_Cliente). Usá
left_on y right_on. Debe incluir García.
Hacé clic en ▶ Ejecutar
Ejercicio 5: Merge + indicator
Hacé un OUTER merge con indicator=True. Contá cuántas filas son "both". Debe dar
2.
Hacé clic en ▶ Ejecutar
Ejercicio 6: Merge + cálculo
Cruzá pedidos con precios y creá la columna "Total" = Cantidad × Precio. Imprimí la suma total
de ventas. Debe incluir 960000.
Hacé clic en ▶ Ejecutar
Ejercicio 7: Detectar "huérfanos" con left merge
Hacé un LEFT merge y encontrá las transacciones sin cliente asociado. Imprimí cuántas son.
Debe dar 1.
Hacé clic en ▶ Ejecutar
Ejercicio 8: Merge encadenado (3 tablas)
Cruzá transacciones → clientes → ciudades. Imprimí las columnas del resultado. Debe incluir
Zona.
Hacé clic en ▶ Ejecutar
Ejercicio 9: concat + groupby
Concatená 3 DataFrames trimestrales, luego hacé groupby por Producto y sumá las ventas. El producto "A" debe
sumar 310.
Hacé clic en ▶ Ejecutar
Ejercicio 10: Pipeline completo — merge + transform + reporte
Cruzá transacciones con clientes (left merge). Rellenálos NaN de Segmento con "Desconocido". Agrupá por
Segmento y reportá total + porcentaje de participación. Debe incluir Premium.
Hacé clic en ▶ Ejecutar
Resumen y conexión
pd.merge()es el JOIN de pandas: cruza tablas por una columna clave compartida.- Los 4 tipos de merge (
inner,left,right,outer) definen qué pasa con filas sin match. left_on/right_onse usan cuando la clave se llama distinto en cada tabla.indicator=Truediagnostica el merge mostrando qué filas tienen match y cuáles no.pd.concat()apila DataFrames con la misma estructura (como UNION ALL de SQL).- Siempre verificá
len()antes y después del merge para detectar duplicaciones inesperadas.
En la siguiente lección (09 · Estadística descriptiva) vas a aprender los fundamentos estadísticos que todo analista debe dominar: medidas de centralidad, dispersión, distribuciones, percentiles y cómo interpretar los números que pandas calcula.
Recursos: pandas docs — Merge, join, concatenate