Cómo fusionar múltiples marcos de datos

Resuelto Vasco Ferreira asked hace 7 años • 13 respuestas

Tengo diferentes marcos de datos y necesito fusionarlos según la columna de fecha. Si solo tuviera dos marcos de datos, podría usar df1.merge(df2, on='date'), para hacerlo con tres marcos de datos, uso df1.merge(df2.merge(df3, on='date'), on='date'), sin embargo, se vuelve realmente complejo e ilegible hacerlo con múltiples marcos de datos.

Todos los marcos de datos tienen una columna en común date, pero no tienen la misma cantidad de filas ni columnas y solo necesito aquellas filas en las que cada fecha es común a cada marco de datos.

Entonces, estoy intentando escribir una función recursiva que devuelva un marco de datos con todos los datos, pero no funcionó. Entonces, ¿cómo debería fusionar varios marcos de datos?

Probé de diferentes maneras y obtuve errores out of rangecomo keyerror 0/1/2/3y can not merge DataFrame with instance of type <class 'NoneType'>.

Este es el guión que escribí:

dfs = [df1, df2, df3] # list of dataframes

def mergefiles(dfs, countfiles, i=0):
    if i == (countfiles - 2): # it gets to the second to last and merges it with the last
        return
    
    dfm = dfs[i].merge(mergefiles(dfs[i+1], countfiles, i=i+1), on='date')
    return dfm

print(mergefiles(dfs, len(dfs)))

Un ejemplo: df_1:

May 19, 2017;1,200.00;0.1%
May 18, 2017;1,100.00;0.1%
May 17, 2017;1,000.00;0.1%
May 15, 2017;1,901.00;0.1%

df_2:

May 20, 2017;2,200.00;1000000;0.2%
May 18, 2017;2,100.00;1590000;0.2%
May 16, 2017;2,000.00;1230000;0.2%
May 15, 2017;2,902.00;1000000;0.2%

df_3:

May 21, 2017;3,200.00;2000000;0.3%
May 17, 2017;3,100.00;2590000;0.3%
May 16, 2017;3,000.00;2230000;0.3%
May 15, 2017;3,903.00;2000000;0.3%

Resultado de fusión esperado:

May 15, 2017;  1,901.00;0.1%;  2,902.00;1000000;0.2%;   3,903.00;2000000;0.3%   
Vasco Ferreira avatar Jun 02 '17 18:06 Vasco Ferreira
Aceptado

Respuesta corta

df_merged = reduce(lambda  left,right: pd.merge(left,right,on=['DATE'],
                                            how='outer'), data_frames)

Respuesta larga

A continuación, se muestra la forma más clara y comprensible de fusionar múltiples marcos de datos si no se trata de consultas complejas.

Simplemente combine con DATE como índice y combine usando el método OUTER (para obtener todos los datos).

import pandas as pd
from functools import reduce

df1 = pd.read_table('file1.csv', sep=',')
df2 = pd.read_table('file2.csv', sep=',')
df3 = pd.read_table('file3.csv', sep=',')

Ahora, básicamente carga todos los archivos que tienes como marco de datos en una lista. Y luego combine los archivos usando mergeo reducefunción.

# compile the list of dataframes you want to merge
data_frames = [df1, df2, df3]

Nota: puede agregar tantos marcos de datos dentro de la lista anterior. Esta es la parte buena de este método. No hay consultas complejas involucradas.

Para mantener los valores que pertenecen a la misma fecha, debe fusionarlos en elDATE

df_merged = reduce(lambda  left,right: pd.merge(left,right,on=['DATE'],
                                            how='outer'), data_frames)

# if you want to fill the values that don't exist in the lines of merged dataframe simply fill with required strings as

df_merged = reduce(lambda  left,right: pd.merge(left,right,on=['DATE'],
                                            how='outer'), data_frames).fillna('void')
  • Ahora, el resultado serán los valores de la misma fecha en las mismas líneas.
  • Puede completar los datos no existentes de diferentes marcos para diferentes columnas usando fillna().

Luego escriba los datos combinados en el archivo csv si lo desea.

pd.DataFrame.to_csv(df_merged, 'merged.txt', sep=',', na_rep='.', index=False)

Esto debería darte

DATE VALUE1 VALUE2 VALUE3 ....

everestial007 avatar Jun 02 '2017 22:06 everestial007

Parece que los datos tienen las mismas columnas, por lo que puedes:

df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)

merged_df = pd.concat([df1, df2])
Daniel Lopes avatar Jun 02 '2017 22:06 Daniel Lopes

functools.reduce y pd.concat son buenas soluciones, pero en términos de tiempo de ejecución, pd.concat es la mejor.

from functools import reduce
import pandas as pd

dfs = [df1, df2, df3, ...]
nan_value = 0

# solution 1 (fast)
result_1 = pd.concat(dfs, join='outer', axis=1).fillna(nan_value)

# solution 2
result_2 = reduce(lambda df_left,df_right: pd.merge(df_left, df_right, 
                                              left_index=True, right_index=True, 
                                              how='outer'), 
                  dfs).fillna(nan_value)
Ismail Hachimi avatar May 27 '2019 10:05 Ismail Hachimi