Fusión de DataFrames: merge y concat
Al finalizar este tema
Podrás diferenciar claramente entre merge y concat, comprenderás los tipos de combinación inner, left, right y outer, y sabrás elegir el método de fusión adecuado en entornos profesionales.
¿Cuándo es necesaria la fusión?
En la práctica, los datos suelen estar distribuidos en varias tablas.
tabla usuarios: tabla pedidos:
┌────┬──────┐ ┌─────────┬────────┬────────┐
│ id │ name │ │ order_id│ user_id│ amount │
├────┼──────┤ ├─────────┼────────┼────────┤
│ 1 │ Alice│ │ 101 │ 1 │ 5000 │
│ 2 │ Bob │ │ 102 │ 2 │ 3000 │
│ 3 │ Carol│ │ 103 │ 1 │ 7000 │
└────┴──────┘ └─────────┴────────┴────────┘Para calcular el "total de pedidos por usuario", es necesario combinar ambas tablas. Esto se denomina fusión.
Fusión: combinar según una clave
merge() es equivalente a la operación JOIN de SQL. Combina dos DataFrames basándose en una columna común (clave).
import pandas as pd
users = pd.DataFrame({ "user_id": [1, 2, 3], "name": ["Alice", "Bob", "Carol"]})
orders = pd.DataFrame({ "order_id": [101, 102, 103], "user_id": [1, 2, 1], "amount": [5000, 3000, 7000]})
result = pd.merge(users, orders, on="user_id")print(result)# user_id name order_id amount# 0 1 Alice 101 5000# 1 1 Alice 103 7000# 2 2 Bob 102 3000Como Alice tiene dos pedidos, se muestra en dos filas. Carol no tiene pedidos, por lo que no aparece en el resultado; este es el comportamiento básico de un inner join.
Tipos de unión
users = pd.DataFrame({ "user_id": [1, 2, 3], "name": ["Alice", "Bob", "Carol"]})
orders = pd.DataFrame({ "order_id": [101, 102, 104], "user_id": [1, 2, 4], "amount": [5000, 3000, 8000]})# user_id=3(Carol) no tiene pedidos, user_id=4 no existe en la tabla de usuariosUnión interna (valor predeterminado)
Solo las claves que existen en ambos conjuntos.
pd.merge(users, orders, on="user_id", how="inner")# user_id name order_id amount# 0 1 Alice 101 5000# 1 2 Bob 102 3000Unión izquierda
Conserva todas las filas del DataFrame izquierdo. Si no hay coincidencia en el DataFrame derecho, se inserta un valor NaN.
pd.merge(users, orders, on="user_id", how="left")# user_id name order_id amount# 0 1 Alice 101.0 5000.0# 1 2 Bob 102.0 3000.0# 2 3 Carol NaN NaNCarol no tiene pedidos, pero aparece en los resultados.
Unión Derecha
Conserva todas las filas del DataFrame derecho.
pd.merge(users, orders, on="user_id", how="right")# user_id name order_id amount# 0 1 Alice 101 5000# 1 2 Bob 102 3000# 2 4 NaN 104 8000El usuario con ID de usuario BP083Pnnnn no está en la tabla de usuarios, pero se incluye en los resultados.
Unión externa
Mantiene todas las filas de ambos lados.
pd.merge(users, orders, on="user_id", how="outer")# user_id name order_id amount# 0 1 Alice 101.0 5000.0# 1 2 Bob 102.0 3000.0# 2 3 Carol NaN NaN# 3 4 NaN 104.0 8000.0Cuando los nombres de las columnas clave difieren
users = pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})orders = pd.DataFrame({"customer_id": [1, 2], "amount": [5000, 3000]})
# uso de left_on / right_onpd.merge(users, orders, left_on="id", right_on="customer_id")# id name customer_id amount# 0 1 Alice 1 5000# 1 2 Bob 2 3000concat: simplemente apilar
concat() concatena DataFrames vertical u horizontalmente sin necesidad de coincidencia de claves.
Vertical (axis=0, valor predeterminado)
jan = pd.DataFrame({"product": ["A", "B"], "sales": [100, 200]})feb = pd.DataFrame({"product": ["A", "B"], "sales": [150, 250]})
quarterly = pd.concat([jan, feb], ignore_index=True)# product sales# 0 A 100# 1 B 200# 2 A 150# 3 B 250Al usar ignore_index=True, el índice se restablece a 0. Si no se usa, se repiten los índices originales (0, 1, 0, 1).
Eje horizontal (axis=1)
info = pd.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})scores = pd.DataFrame({"math": [90, 85], "english": [88, 92]})
combined = pd.concat([info, scores], axis=1)# name age math english# 0 Alice 30 90 88# 1 Bob 25 85 92Combinar vs. concatenar: ¿cuándo usar cada uno?
| Combinar | Concatenar | |
|---|---|---|
| Propósito | Combinar datos mediante la correspondencia de claves comunes | Simplemente apilar o concatenar |
| Analogía en SQL | JOIN | UNION |
| Requiere clave | Sí (on, left_on/right_on) | No |
| Dirección | Horizontal (agrega columnas) | Vertical u horizontal |
| Casos de uso | Usuario + pedido, producto + categoría | Combinar datos mensuales, combinar archivos divididos |
"Conectar usuarios y pedidos" → merge (coincidencia por clave)
"Unir datos de enero y febrero" → concat (apilado simple)Consideraciones al fusionar: duplicados e inconsistencias de claves
Expansión de filas en la fusión de muchos a muchos
# un user_id con múltiples pedidos, múltiples envíosorders = pd.DataFrame({ "user_id": [1, 1, 1], "order_id": [101, 102, 103]})shipments = pd.DataFrame({ "user_id": [1, 1], "shipment_id": ["S1", "S2"]})
result = pd.merge(orders, shipments, on="user_id")print(len(result)) # ¡6! (3 × 2 = producto cartesiano)Si hay varias claves idénticas en ambos lados, se generan todas las combinaciones posibles. 3 filas × 2 filas = 6 filas. En conjuntos de datos grandes, esta operación de combinación puede provocar un consumo excesivo de memoria. Se puede evitar utilizando el parámetro validate:
pd.merge(orders, shipments, on="user_id", validate="many_to_one")# MergeError: Merge keys are not unique in right datasetPatrón práctico: Combinar varios archivos
import osimport pandas as pd
data_dir = "monthly_reports"all_dfs = []
for filename in sorted(os.listdir(data_dir)): if filename.endswith(".csv"): filepath = os.path.join(data_dir, filename) df = pd.read_csv(filepath) df["source_file"] = filename all_dfs.append(df)
combined = pd.concat(all_dfs, ignore_index=True)print(f"Total rows: {len(combined)}")Este es el patrón para combinar archivos CSV mensuales en un solo archivo. Se puede agregar la columna source_file para realizar un seguimiento del origen de cada registro.
Resumen clave
| Función | Propósito | Parámetros clave |
|---|---|---|
merge() | Fusión basada en claves (JOIN) | on, how, left_on/right_on |
concat() | Concatenación (UNION) | axis, ignore_index |
| Tipo de JOIN | Alcance |
|---|---|
| inner | Solo las claves presentes en ambos conjuntos de datos |
| left | Todos los registros del conjunto de datos izquierdo, más las coincidencias del conjunto de datos derecho |
| right | Todos los registros del conjunto de datos derecho, más las coincidencias del conjunto de datos izquierdo |
| outer | Todos los registros de ambos conjuntos de datos (se muestran valores NaN si no hay coincidencia) |
El 80% del análisis de datos consiste en combinar la tabla correcta de la manera correcta. Comprender claramente la diferencia entre merge y concat, así como el funcionamiento de los cuatro tipos de JOIN, permite prevenir los errores más comunes en el preprocesamiento de datos: filas duplicadas, gran cantidad de valores NaN e inconsistencias en las claves.