2 votes

Python Pandas - accélérer la jointure csv

J'ai un problème d'optimisation. J'ai besoin de joindre quelques csv (tous ont la même structure) en un csv unique.

La structure de mes dossiers suit un ordre temporel : année/mois/jour/heure_identifiant_de_fichier.csv. Donc 16a*365j*24h = 140160 fichiers. C'est le nombre maximum de fichiers que je peux avoir comme résultat. Chaque dossier indexé par jour peut contenir un nombre arbitraire de fichiers (que je génère avec un script python également). Comme le nombre de fichiers dépassera le maximum autorisé pour un système de fichiers ext4 toutes les N itérations, j'ai besoin de joindre tous les fichiers dans les fichiers indexés par heure, pour ne pas rencontrer ce problème.

Ainsi, l'entrée de ce que j'appelle join_routine est la liste des dossiers indexés par heure, par exemple :

2001/9/3/
2002/8/4/

Chacun de ces dossiers peut contenir un nombre variable de fichiers :

2001/9/3/
    1-01.csv
    1-02.csv
    2-01.csv
2002/8/4/
    1-01.csv
    2-01.csv
    3-01.csv
    3-01.csv

Les résultats de l'enquête join_routine devrait être :

2001/9/3/
    1-joined.csv
    2-joined.csv
2002/8/4/
    1-joined.csv
    2-joined.csv
    3-joined.csv

Pour ce faire, je développe le code suivant :

def join_routine():
#    print('JOIN ROUTINE')
    directory_list = [x.replace('\\','/') for x in glob.glob('data/csv/plays/*/*/*/')]

    for directory in directory_list:
        for hour in range(0,13):
            file_list = [x.replace('\\','/') for x in glob.glob(directory+ str(hour) +'-*.csv')]
            if len(file_list) > 0:
                df = read_csv_list(file_list)
                df.to_csv(directory+str(hour)+'-joined.csv', index = False)
                for file in [ x for x in file_list if x not in directory+str(hour)+'-joined.csv']:
                    os.remove(file)

def read_csv_list(file_list):
    df_list = []
#    with progressbar.ProgressBar(max_value=len(file_list)) as bar:
#        i = 0
    for file in file_list:
        df = pd.read_csv(file)
        df_list.append(df)
#            i = i + 1
#            bar.update(i)

    return pd.concat(df_list, axis = 0, ignore_index = True)

Les join_routine gère la jonction de chaque dossier en un seul processus. Je me demande s'il n'y a pas un meilleur moyen, et surtout un moyen plus rapide, de faire cela. La fonction join_routine prend plus de 10X la création de fichiers (qui est effectuée sur un pool de processus parallèles de 16 travailleurs). J'ai besoin de faire le join_routine 21 fois et va prendre plus d'une semaine à ce rythme, ce qui n'est pas envisageable. Une idée ?

2voto

keineahnung2345 Points 1968

Mais n'utilisez pas de pandas !

Expérience 1 : Lire un fichier et l'ajouter à un autre ligne par ligne (code adopté à partir de comment fusionner 200 fichiers csv en Python ):

import time

#%%
start1 = time.time()
fout=open("out.csv","a")
# first file:
for line in open("file.csv"):
    fout.write(line)
# now the rest:    
for num in range(2,201):
    f = open("file.csv")
    f.__next__() # skip the header
    for line in f:
         fout.write(line)
    f.close() # not really needed
fout.close()
end1 = time.time()
print(end1-start1) #0.3000311851501465

Expérience 2 (Utilisation de pandas pour lire, concaténer et écrire des fichiers csv) :

import time
import pandas as pd
start2 = time.time()
df_list = []
for i in range(200):
    df = pd.read_csv('file.csv')
    df_list.append(df)
df = pd.concat(df_list, axis = 0, ignore_index = True)
df.to_csv('out2.csv', index = False)
end2 = time.time()
print(end2-start2) #3.0119707584381104

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