182 votes

Python: les pandas fusionnent plusieurs cadres de données

J'ai diferent dataframes et la nécessité de les fusionner, basé sur la colonne date. Si seulement j'avais deux dataframes, je pourrais utiliser df1.merge(df2, on='date'), pour le faire avec trois dataframes, j'utilise df1.merge(df2.merge(df3, on='date'), on='date'), cependant, il devient vraiment très complexe et illisible pour le faire avec plusieurs dataframes.

Tous les dataframes ont une colonne en commun -date, mais ils n'ont pas le même nombre de lignes ou de colonnes et je n'ai plus besoin de ces lignes dans lequel chaque jour est commune à toutes les dataframe.

Donc, je suis en train d'écrire une récursivité fonction qui retourne un dataframe avec toutes les données, mais il ne fonctionne pas. Comment dois-je les fusionner plusieurs dataframes alors?

J'ai essayé de différentes façons et eu des erreurs comme out of range, keyerror 0/1/2/3 et can not merge DataFrame with instance of type <class 'NoneType'>.

C'est le script que j'ai écrit:

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 exemple: 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%

Attendue du résultat de la fusion:

May 15, 2017;  1,901.00;0.1%;  2,902.00;1000000;0.2%;   3,903.00;2000000;0.3%   

313voto

everestial007 Points 1132

Ci-dessous, est la plus propre, de manière compréhensible de la fusion de plusieurs dataframe si des requêtes complexes ne sont pas impliqués.

Tout simplement fusionner avec la DATE , l'indice et de fusion à l'aide EXTÉRIEURE de la méthode (pour obtenir toutes les données).

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=',')

Donc, en gros, de charger tous les fichiers que vous avez comme trame de données. Puis de fusionner des fichiers à l'aide de merge ou reduce fonction.

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

vous pouvez ajouter autant de données d'images dans le code ci-dessus. C'est la bonne partie de cette méthode. Pas de requêtes complexes impliqués.

Pour conserver les valeurs qui appartiennent à la même date que vous avez besoin de fusionner sur l' DATE

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')
  • Ainsi, les valeurs à partir de la même date, sont sur les mêmes lignes.
  • Vous pouvez remplir la non-existence de données à partir de différentes images pour les différentes colonnes à l'aide de fillna().

Ensuite, écrivez la fusion de données dans le fichier csv si vous le souhaitez.

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

Cela devrait vous donner

DATE VALUE1 VALUE2 VALUE3 ....

59voto

dannyeuu Points 141

On dirait que les données ont les mêmes colonnes, vous pouvez donc:

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

merged_df = pd.concat([df1, df2])
 

40voto

functools.reduce et pd.concat sont de bonnes solutions mais en terme de temps d'exécution pd.concat est le meilleur.

 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 left,right: pd.merge(df_left, df_right, 
                                              left_index=True, right_index=True, 
                                              how='outer'), 
                  dfs).fillna(nan_value)
 

19voto

jezrael Points 290608

Il existe 2 solutions pour cela, mais il retourne toutes les colonnes séparément:

 import functools

dfs = [df1, df2, df3]

df_final = functools.reduce(lambda left,right: pd.merge(left,right,on='date'), dfs)
print (df_final)
          date     a_x   b_x       a_y      b_y   c_x         a        b   c_y
0  May 15,2017  900.00  0.2%  1,900.00  1000000  0.2%  2,900.00  2000000  0.2%

k = np.arange(len(dfs)).astype(str)
df = pd.concat([x.set_index('date') for x in dfs], axis=1, join='inner', keys=k)
df.columns = df.columns.map('_'.join)
print (df)
                0_a   0_b       1_a      1_b   1_c       2_a      2_b   2_c
date                                                                       
May 15,2017  900.00  0.2%  1,900.00  1000000  0.2%  2,900.00  2000000  0.2%
 

5voto

Allen Wang Points 908

La réponse de @ dannyeuu est correcte. pd.concat fait naturellement une jointure sur les colonnes d'index, si vous définissez l'option d'axe sur 1. La valeur par défaut est une jointure externe, mais vous pouvez également spécifier la jointure interne. Voici un exemple:

 x = pd.DataFrame({'a': [2,4,3,4,5,2,3,4,2,5], 'b':[2,3,4,1,6,6,5,2,4,2], 'val': [1,4,4,3,6,4,3,6,5,7], 'val2': [2,4,1,6,4,2,8,6,3,9]})
x.set_index(['a','b'], inplace=True)
x.sort_index(inplace=True)

y = x.__deepcopy__()
y.loc[(14,14),:] = [3,1]
y['other']=range(0,11)

y.sort_values('val', inplace=True)

z = x.__deepcopy__()
z.loc[(15,15),:] = [3,4]
z['another']=range(0,22,2)
z.sort_values('val2',inplace=True)


pd.concat([x,y,z],axis=1)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X