Pandas Concat: Cómo concatenar DataFrames en Python
Updated on
Los datos del mundo real rara vez se encuentran en un solo archivo. Usted extrae las ventas de enero de un CSV, las de febrero de otro y los objetivos del Q1 de un tercero. Hace scraping de múltiples páginas web en DataFrames separados. Divide un conjunto de datos grande para procesamiento paralelo y necesita volver a ensamblar las piezas. En todos los casos, necesita una forma confiable de combinar DataFrames sin perder filas, desordenar columnas o corromper su índice.
La función pandas concat (pd.concat()) es la herramienta estándar para esta tarea. Apila DataFrames verticalmente (agregando filas) u horizontalmente (agregando columnas), maneja columnas diferentes con elegancia y escala a cualquier cantidad de DataFrames en una sola llamada. Esta guía cubre cada parámetro que necesita, con ejemplos de código funcionales que puede pegar directamente en su notebook.
Qué hace pd.concat() -- Sintaxis básica
pd.concat() toma una lista (o diccionario) de DataFrames y los une a lo largo de un eje especificado. Piense en ello como apilar bloques de construcción -- verticalmente para agregar más filas, o lado a lado para agregar más columnas.
import pandas as pd
result = pd.concat(
objs, # list or dict of DataFrames
axis=0, # 0 = vertical (rows), 1 = horizontal (columns)
join='outer', # 'outer' or 'inner'
ignore_index=False,
keys=None,
sort=False,
verify_integrity=False
)Parámetros clave de un vistazo
| Parámetro | Descripción | Predeterminado |
|---|---|---|
objs | Una lista o diccionario de DataFrames (o Series) para concatenar | Requerido |
axis | 0 para apilar filas (vertical), 1 para apilar columnas (horizontal) | 0 |
join | 'outer' conserva todas las columnas; 'inner' conserva solo las columnas compartidas | 'outer' |
ignore_index | Si es True, restablece el índice a 0, 1, 2, ... en el resultado | False |
keys | Etiquetas para identificar de qué DataFrame original proviene cada fila | None |
sort | Ordenar el eje de no concatenación (nombres de columnas para axis=0) | False |
verify_integrity | Lanzar error si el resultado tiene valores de índice duplicados | False |
Datos de ejemplo para todos los ejemplos
Todos los ejemplos a continuación utilizan estos DataFrames:
import pandas as pd
df_jan = pd.DataFrame({
'product': ['Widget', 'Gadget', 'Sprocket'],
'units_sold': [150, 200, 80],
'revenue': [1500, 3000, 960]
})
df_feb = pd.DataFrame({
'product': ['Widget', 'Gadget', 'Sprocket'],
'units_sold': [170, 180, 95],
'revenue': [1700, 2700, 1140]
})
print(df_jan)
print(df_feb)Salida:
product units_sold revenue
0 Widget 150 1500
1 Gadget 200 3000
2 Sprocket 80 960
product units_sold revenue
0 Widget 170 1700
1 Gadget 180 2700
2 Sprocket 95 1140Concatenar DataFrames verticalmente (axis=0)
La concatenación vertical es el caso de uso más común. Apila un DataFrame encima de otro, agregando filas. Esto es lo que usa cuando tiene archivos mensuales, resultados por lotes o cualquier dato dividido en múltiples tablas con las mismas columnas.
combined = pd.concat([df_jan, df_feb])
print(combined)Salida:
product units_sold revenue
0 Widget 150 1500
1 Gadget 200 3000
2 Sprocket 80 960
0 Widget 170 1700
1 Gadget 180 2700
2 Sprocket 95 1140Observe el índice: ambos DataFrames mantuvieron sus valores de índice originales (0, 1, 2), por lo que el resultado tiene valores de índice duplicados. Esto generalmente no es lo que desea. La solución es el parámetro ignore_index, que se cubre a continuación.
El parámetro ignore_index -- Restablecer el índice
Establecer ignore_index=True descarta el índice original y asigna un nuevo índice secuencial comenzando desde 0:
combined = pd.concat([df_jan, df_feb], ignore_index=True)
print(combined)Salida:
product units_sold revenue
0 Widget 150 1500
1 Gadget 200 3000
2 Sprocket 80 960
3 Widget 170 1700
4 Gadget 180 2700
5 Sprocket 95 1140Cuándo usarlo: Casi siempre al concatenar verticalmente. A menos que su índice contenga información significativa (como marcas de tiempo o IDs únicos), restablézcalo para evitar confusiones posteriores.
El parámetro keys -- Crear un índice jerárquico
El parámetro keys agrega un nivel al índice que etiqueta de qué fuente proviene cada fila. Esto crea un MultiIndex (índice jerárquico):
combined = pd.concat([df_jan, df_feb], keys=['January', 'February'])
print(combined)Salida:
product units_sold revenue
January 0 Widget 150 1500
1 Gadget 200 3000
2 Sprocket 80 960
February 0 Widget 170 1700
1 Gadget 180 2700
2 Sprocket 95 1140Luego puede seleccionar datos de una fuente específica usando .loc:
# Get only January data
jan_data = combined.loc['January']
print(jan_data)Salida:
product units_sold revenue
0 Widget 150 1500
1 Gadget 200 3000
2 Sprocket 80 960Cuándo usarlo: Use keys cuando necesite rastrear a qué DataFrame original pertenece cada fila -- por ejemplo, datos de diferentes experimentos, períodos de tiempo o fuentes de datos.
Concatenar horizontalmente (axis=1) -- Lado a lado
Establecer axis=1 coloca los DataFrames uno al lado del otro, agregando columnas. Pandas alinea las filas por sus valores de índice.
targets = pd.DataFrame({
'target_units': [160, 190, 90],
'target_revenue': [1600, 2850, 1080]
})
result = pd.concat([df_jan, targets], axis=1)
print(result)Salida:
product units_sold revenue target_units target_revenue
0 Widget 150 1500 160 1600
1 Gadget 200 3000 190 2850
2 Sprocket 80 960 90 1080Esto funciona correctamente porque ambos DataFrames comparten el mismo índice (0, 1, 2). Si los índices no se alinean, obtendrá valores NaN para las filas que no coinciden:
df_a = pd.DataFrame({'value_a': [10, 20, 30]}, index=[0, 1, 2])
df_b = pd.DataFrame({'value_b': [40, 50, 60]}, index=[1, 2, 3])
result = pd.concat([df_a, df_b], axis=1)
print(result)Salida:
value_a value_b
0 10.0 NaN
1 20.0 40.0
2 30.0 50.0
3 NaN 60.0La fila 0 no tiene value_b (no hay índice correspondiente en df_b), y la fila 3 no tiene value_a (no hay índice correspondiente en df_a).
El parámetro join -- Inner vs Outer
El parámetro join controla qué sucede cuando los DataFrames tienen diferentes columnas (para axis=0) o diferentes valores de índice (para axis=1).
outer join (predeterminado) -- Conservar todo
df_with_extra = pd.DataFrame({
'product': ['Widget', 'Gadget'],
'units_sold': [200, 250],
'region': ['East', 'West']
})
result = pd.concat([df_jan, df_with_extra], join='outer', ignore_index=True)
print(result)Salida:
product units_sold revenue region
0 Widget 150 1500.0 NaN
1 Gadget 200 3000.0 NaN
2 Sprocket 80 960.0 NaN
3 Widget 200 NaN East
4 Gadget 250 NaN WestTodas las columnas de ambos DataFrames aparecen. Los valores faltantes se llenan con NaN.
inner join -- Conservar solo columnas compartidas
result = pd.concat([df_jan, df_with_extra], join='inner', ignore_index=True)
print(result)Salida:
product units_sold
0 Widget 150
1 Gadget 200
2 Sprocket 80
3 Widget 200
4 Gadget 250Solo sobreviven las columnas que existen en ambos DataFrames. La columna revenue (ausente en df_with_extra) y la columna region (ausente en df_jan) se eliminan.
Cuándo usar inner join: Cuando desea un resultado limpio sin valores NaN y está dispuesto a perder columnas que no aparecen en todos los DataFrames.
Concatenar una lista de DataFrames
Una de las mayores ventajas de pd.concat() sobre otros métodos de combinación es que maneja cualquier cantidad de DataFrames en una sola llamada. Este es el patrón estándar para combinar archivos cargados en un bucle:
import pandas as pd
# Simulate loading monthly CSV files
months = {
'Jan': {'product': ['Widget', 'Gadget'], 'units': [150, 200]},
'Feb': {'product': ['Widget', 'Gadget'], 'units': [170, 180]},
'Mar': {'product': ['Widget', 'Gadget'], 'units': [190, 210]},
}
dfs = []
for month, data in months.items():
df = pd.DataFrame(data)
df['month'] = month
dfs.append(df)
all_data = pd.concat(dfs, ignore_index=True)
print(all_data)Salida:
product units month
0 Widget 150 Jan
1 Gadget 200 Jan
2 Widget 170 Feb
3 Gadget 180 Feb
4 Widget 190 Mar
5 Gadget 210 MarEste patrón -- construir una lista de DataFrames y luego llamar a concat una vez al final -- es mucho más rápido que agregar un DataFrame a la vez en un bucle. Cada append crea una copia completa, pero una sola llamada a pd.concat() asigna memoria una sola vez.
concat vs merge vs append -- Tabla comparativa
Pandas ofrece varias formas de combinar DataFrames. Elegir la correcta depende de cómo desea combinarlos:
| Característica | pd.concat() | pd.merge() | DataFrame.append() |
|---|---|---|---|
| Uso principal | Apilar DataFrames (filas o columnas) | Unir por valores de columna compartidos (como SQL) | Agregar filas a un DataFrame |
| Número de entradas | Cualquier cantidad a la vez | Dos a la vez | Dos a la vez |
| Lógica de coincidencia | Alinea por índice (o nombres de columna) | Coincide por valores de columna clave | Alinea por nombres de columna |
| Tipos de join | outer, inner | inner, left, right, outer, cross | Solo outer |
| Comportamiento predeterminado | Outer join, apilar verticalmente | Inner join en columnas compartidas | Outer join, agregar filas |
| Mejor para | Combinar archivos mensuales, resultados por lotes, tablas con el mismo esquema | Joins relacionales (clientes + pedidos) | Obsoleto desde pandas 2.0 |
| Rendimiento | Rápido para muchos DataFrames | Optimizado para joins de dos tablas | Lento (copia datos en cada llamada) |
Cuándo usar cada uno
- Use
pd.concat()cuando sus DataFrames comparten la misma estructura (mismas columnas) y desea apilarlos. También úselo para concatenación horizontal al alinear por índice. - Use
pd.merge()cuando necesite hacer coincidir filas basándose en valores de columna -- como unir una tabla de ventas con una tabla de productos porproduct_id. Consulte nuestra guía de pandas merge para más detalles. - Evite
DataFrame.append()-- fue obsoleto en pandas 1.4 y eliminado en pandas 2.0. Usepd.concat([df1, df2])en su lugar.
Errores comunes y soluciones
1. Las columnas no se alinean
Al concatenar DataFrames con diferentes nombres de columna, el outer join predeterminado llena los valores faltantes con NaN. Si no esperaba esto, verifique los nombres de sus columnas:
# Diagnose: compare column names
print(df1.columns.tolist())
print(df2.columns.tolist())
# Fix: rename columns to match before concatenating
df2 = df2.rename(columns={'sales': 'revenue', 'qty': 'units_sold'})
combined = pd.concat([df1, df2], ignore_index=True)2. Discrepancias de tipos de datos después de la concatenación
Si un DataFrame almacena una columna como int64 y otro como float64, pandas convierte a float. Peor aún, si uno la almacena como string, obtiene una columna con dtype object:
# Check dtypes after concat
combined = pd.concat([df1, df2], ignore_index=True)
print(combined.dtypes)
# Fix: cast before concatenating
df2['units_sold'] = df2['units_sold'].astype(int)
combined = pd.concat([df1, df2], ignore_index=True)3. Valores de índice duplicados
Sin ignore_index=True, la concatenación vertical preserva los índices originales, lo que lleva a valores duplicados. Esto causa problemas con las búsquedas .loc:
combined = pd.concat([df1, df2])
# combined.loc[0] returns TWO rows, not one
# Fix option 1: use ignore_index
combined = pd.concat([df1, df2], ignore_index=True)
# Fix option 2: use verify_integrity to catch the issue early
combined = pd.concat([df1, df2], verify_integrity=True) # raises ValueError4. Concatenación accidental a lo largo del eje equivocado
Si su resultado tiene el doble de columnas en lugar del doble de filas (o viceversa), verifique el parámetro axis:
# Wrong: this adds columns side by side
wrong = pd.concat([df1, df2], axis=1)
# Right: this stacks rows vertically
right = pd.concat([df1, df2], axis=0)Visualice sus DataFrames concatenados con PyGWalker
Después de concatenar datos de múltiples fuentes, a menudo necesita verificar el resultado y explorar patrones en el conjunto de datos combinado. En lugar de escribir código de gráficos manual con matplotlib o seaborn, puede usar PyGWalker (opens in a new tab) -- una biblioteca de Python de código abierto que convierte cualquier DataFrame de pandas en una interfaz de exploración visual interactiva, similar a Tableau, directamente dentro de Jupyter Notebook.
import pandas as pd
import pygwalker as pyg
# Combine monthly sales data
df_jan = pd.DataFrame({
'product': ['Widget', 'Gadget', 'Sprocket'],
'units_sold': [150, 200, 80],
'revenue': [1500, 3000, 960],
'month': ['Jan', 'Jan', 'Jan']
})
df_feb = pd.DataFrame({
'product': ['Widget', 'Gadget', 'Sprocket'],
'units_sold': [170, 180, 95],
'revenue': [1700, 2700, 1140],
'month': ['Feb', 'Feb', 'Feb']
})
combined = pd.concat([df_jan, df_feb], ignore_index=True)
# Launch interactive visualization
walker = pyg.walk(combined)Con PyGWalker, puede arrastrar product al eje x y revenue al eje y, luego dividir por month para comparar instantáneamente las tendencias de ingresos entre períodos -- sin necesidad de código de gráficos. Puede crear gráficos de barras, diagramas de dispersión, gráficos de líneas y más simplemente arrastrando campos. Es especialmente útil para verificar que su concatenación funcionó correctamente y que los datos de diferentes fuentes se alinean como se esperaba.
Instale PyGWalker con
pip install pygwalker, o pruébelo en Google Colab (opens in a new tab) o Kaggle (opens in a new tab).
FAQ
¿Cuál es la diferencia entre pandas concat y merge?
pd.concat() apila DataFrames verticalmente (agregando filas) u horizontalmente (agregando columnas) alineando por el índice. pd.merge() une dos DataFrames haciendo coincidir valores en columnas específicas, como un SQL JOIN. Use concat cuando sus DataFrames tengan las mismas columnas y quiera combinar filas. Use merge cuando necesite hacer coincidir filas basándose en una columna clave compartida.
¿pd.concat() modifica los DataFrames originales?
No. pd.concat() siempre devuelve un nuevo DataFrame. Los DataFrames originales permanecen sin cambios. Esto es consistente con el principio de diseño de pandas de que las operaciones devuelven nuevos objetos en lugar de modificar los datos en su lugar.
¿Cómo concateno DataFrames con diferentes columnas?
Use pd.concat() con el valor predeterminado join='outer' -- mantiene todas las columnas de todos los DataFrames y llena los valores faltantes con NaN. Si solo quiere columnas que aparezcan en todos los DataFrames, establezca join='inner'. También puede renombrar columnas antes de concatenar para asegurar la alineación.
¿Es pd.concat() más rápido que DataFrame.append()?
Sí. DataFrame.append() fue obsoleto en pandas 1.4 y eliminado en pandas 2.0. Llamaba internamente a pd.concat() pero creaba una copia en cada llamada. Al combinar muchos DataFrames, recopilarlos en una lista y llamar a pd.concat() una vez es significativamente más rápido porque asigna memoria una sola vez.
¿Cómo restablezco el índice después de la concatenación?
Pase ignore_index=True a pd.concat(): pd.concat([df1, df2], ignore_index=True). Esto reemplaza los valores de índice originales con un nuevo índice secuencial comenzando desde 0. Alternativamente, llame a .reset_index(drop=True) en el resultado.
Conclusión
La función pandas concat() es la herramienta preferida para combinar DataFrames que comparten la misma estructura. Aquí están los puntos clave:
- Concatenación vertical (
axis=0) apila filas y es el caso de uso más común -- ideal para combinar archivos mensuales, resultados por lotes o conjuntos de datos divididos. - Concatenación horizontal (
axis=1) coloca DataFrames lado a lado, alineando por el índice. - Use
ignore_index=Truepara obtener un índice secuencial limpio (recomendado en la mayoría de los casos). - Use
keyspara crear un índice jerárquico que rastrea de qué fuente proviene cada fila. - El parámetro
joincontrola cómo se manejan las columnas que no coinciden:'outer'conserva todo,'inner'conserva solo las columnas compartidas. - Siempre recopile DataFrames en una lista y llame a
pd.concat()una vez, en lugar de agregar en un bucle. - Use
pd.merge()cuando necesite joins estilo SQL en valores de columna.
Una vez que sus datos están concatenados, herramientas como PyGWalker (opens in a new tab) le permiten explorar visualmente el resultado combinado sin escribir código de gráficos, haciendo más rápido verificar su pipeline de datos y descubrir patrones entre fuentes.