Publicado el: 19 de Diciembre del 2020 - Jhonatan Montilla
Pandas proporciona varias funciones integradas para combinar fácilmente DataFrames. Entre ellos, la función concat() parece bastante sencilla de usar, pero todavía hay muchos trucos que debe conocer para acelerar su análisis de datos.
En este artículo, aprenderá a tratar con los siguientes inconvenientes comunes:
Primeramente se procede a la carga de las librerías
import pandas as pd
import numpy as np
import pathlib2 as pl2
Se tienen dos conjuntos de datos sobre las calificaciones de exámenes de un grupo de alumnos.
df1 = pd.DataFrame({
'name': ['A', 'B', 'C', 'D'],
'math': [60,89,82,70],
'physics': [66,95,83,66],
'chemistry': [61,91,77,70]
})
df2 = pd.DataFrame({
'name': ['E', 'F', 'G', 'H'],
'math': [66,95,83,66],
'physics': [60,89,82,70],
'chemistry': [90,81,78,90]
})
La concatenación es bastante simple con la función concat(), consiste en pasar una lista de DataFrames, por ejemplo [df1, df2]. Y de manera predeterminada, está concatenando verticalmente a lo largo del eje 0 y conservando todos los índices existentes.
Si desea que la concatenación ignore los índices existentes, puede establecer el argumento ignore_index = True. Luego, el índice DataFrame resultante se etiquetará con 0,…, n-1.
pd.concat([df1, df2], ignore_index=True)
name | math | physics | chemistry | |
---|---|---|---|---|
0 | A | 60 | 66 | 61 |
1 | B | 89 | 95 | 91 |
2 | C | 82 | 83 | 77 |
3 | D | 70 | 66 | 70 |
4 | E | 66 | 60 | 90 |
5 | F | 95 | 89 | 81 |
6 | G | 83 | 82 | 78 |
7 | H | 66 | 70 | 90 |
pd.concat([df1, df2], axis=1)
name | math | physics | chemistry | name | math | physics | chemistry | |
---|---|---|---|---|---|---|---|---|
0 | A | 60 | 66 | 61 | E | 66 | 60 | 90 |
1 | B | 89 | 95 | 91 | F | 95 | 89 | 81 |
2 | C | 82 | 83 | 77 | G | 83 | 82 | 78 |
3 | D | 70 | 66 | 70 | H | 66 | 70 | 90 |
try:
pd.concat([df1,df2], verify_integrity=True)
except ValueError as e:
print('ValueError', e)
ValueError Indexes have overlapping values: Int64Index([0, 1, 2, 3], dtype='int64')
Es muy útil agregar un índice jerárquico (también conocido como índice multinivel) para un análisis de datos más sofisticado. En este caso, se agrega el año 1 y el año 2 del índice para df1 y df2 respectivamente. Para hacer esto, simplemente se especifica el argumento en las claves.
res = pd.concat([df1, df2], keys=['Year 1','Year 2'])
res
name | math | physics | chemistry | ||
---|---|---|---|---|---|
Year 1 | 0 | A | 60 | 66 | 61 |
1 | B | 89 | 95 | 91 | |
2 | C | 82 | 83 | 77 | |
3 | D | 70 | 66 | 70 | |
Year 2 | 0 | E | 66 | 60 | 90 |
1 | F | 95 | 89 | 81 | |
2 | G | 83 | 82 | 78 | |
3 | H | 66 | 70 | 90 |
res.loc['Year 1']
name | math | physics | chemistry | |
---|---|---|---|---|
0 | A | 60 | 66 | 61 |
1 | B | 89 | 95 | 91 |
2 | C | 82 | 83 | 77 |
3 | D | 70 | 66 | 70 |
pd.concat(
[df1, df2],
keys=['Year 1', 'Year 2'],
names=['Class', None],
)
name | math | physics | chemistry | ||
---|---|---|---|---|---|
Class | |||||
Year 1 | 0 | A | 60 | 66 | 61 |
1 | B | 89 | 95 | 91 | |
2 | C | 82 | 83 | 77 | |
3 | D | 70 | 66 | 70 | |
Year 2 | 0 | E | 66 | 60 | 90 |
1 | F | 95 | 89 | 81 | |
2 | G | 83 | 82 | 78 | |
3 | H | 66 | 70 | 90 |
pd.concat(
[df1, df2],
keys=['Year 1', 'Year 2'],
names=['Class', None],
).reset_index(level=0)
# reset_index(level='Class')
Class | name | math | physics | chemistry | |
---|---|---|---|---|---|
0 | Year 1 | A | 60 | 66 | 61 |
1 | Year 1 | B | 89 | 95 | 91 |
2 | Year 1 | C | 82 | 83 | 77 |
3 | Year 1 | D | 70 | 66 | 70 |
0 | Year 2 | E | 66 | 60 | 90 |
1 | Year 2 | F | 95 | 89 | 81 |
2 | Year 2 | G | 83 | 82 | 78 |
3 | Year 2 | H | 66 | 70 | 90 |
La función concat() puede concatenar DataFrames con las columnas en un orden diferente. De forma predeterminada, el DataFrame resultante tendría la misma clasificación que el primer DataFrame. Por ejemplo, en el siguiente ejemplo, es el mismo orden que df1.
pd.concat([df1, df2], sort=True)
chemistry | math | name | physics | |
---|---|---|---|---|
0 | 61 | 60 | A | 66 |
1 | 91 | 89 | B | 95 |
2 | 77 | 82 | C | 83 |
3 | 70 | 70 | D | 66 |
0 | 90 | 66 | E | 60 |
1 | 81 | 95 | F | 89 |
2 | 78 | 83 | G | 82 |
3 | 90 | 66 | H | 70 |
custom_sort = ['math', 'chemistry', 'physics', 'name']
res = pd.concat([df1, df2])
res[custom_sort]
math | chemistry | physics | name | |
---|---|---|---|---|
0 | 60 | 61 | 66 | A |
1 | 89 | 91 | 95 | B |
2 | 82 | 77 | 83 | C |
3 | 70 | 70 | 66 | D |
0 | 66 | 90 | 60 | E |
1 | 95 | 81 | 89 | F |
2 | 83 | 78 | 82 | G |
3 | 66 | 90 | 70 | H |
df1.to_csv("test/df1.csv", sep=",", index=False)
df2.to_csv("test/df2.csv", sep=",", index=False)
Supongamos que necesitamos cargar y concatenar conjuntos de datos desde varios archivos .CSV contenidos en un directorio, a través de un bucle for se puede efectuar dicha tarea.
ps = pl2.Path('test/')
dfs = (
pd.read_csv(p, encoding='utf8') for p in ps.glob('*.csv')
)
res = pd.concat(dfs)
res
name | math | physics | chemistry | |
---|---|---|---|---|
0 | A | 60 | 66 | 61 |
1 | B | 89 | 95 | 91 |
2 | C | 82 | 83 | 77 |
3 | D | 70 | 66 | 70 |
0 | E | 66 | 60 | 90 |
1 | F | 95 | 89 | 81 |
2 | G | 83 | 82 | 78 |
3 | H | 66 | 70 | 90 |
Una sola línea de código lee todos los archivos .CSV y genera una lista de DataFrames dfs. Luego, solo necesitamos llamar a pd.concat (dfs) una vez para obtener el mismo resultado.
Si desea calcula el tiempo de ambas ejecuciones, lo puede hacer utilizando %% timeit, probablemente encontrará que esta solución ahorra la mitad del tiempo.
La concatenación de varios conjuntos de datos ahorra tiempo y códigos. Es una manera sencilla de generar una lista en comparación con el uso de bucles.