J'utilise actuellement le code ci-dessous pour importer 6 000 fichiers csv (avec en-têtes) et les exporter dans un seul fichier csv (avec une seule ligne d'en-tête).
#import csv files from folder
path =r'data/US/market/merged_data'
allFiles = glob.glob(path + "/*.csv")
stockstats_data = pd.DataFrame()
list_ = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None,)
list_.append(df)
stockstats_data = pd.concat(list_)
print(file_ + " has been imported.")
Ce code fonctionne bien, mais il est lent. Le traitement peut prendre jusqu'à 2 jours.
On m'a donné un script de ligne unique pour la ligne de commande du terminal qui fait la même chose (mais sans en-têtes). Ce script prend 20 secondes.
for f in *.csv; do cat "`pwd`/$f" | tail -n +2 >> merged.csv; done
Est-ce que quelqu'un sait comment accélérer le premier script Python? Pour réduire le temps, j'ai pensé à ne pas l'importer dans un DataFrame et à concaténer simplement les CSV, mais je ne peux pas le comprendre .
Merci.
Si vous n'avez pas besoin du CSV en mémoire, il suffit de copier de l'entrée vers la sortie, ce sera beaucoup moins cher pour éviter l'analyse du tout, et copier sans construire en mémoire:
import shutil
#import csv files from folder
path = r'data/US/market/merged_data'
allFiles = glob.glob(path + "/*.csv")
with open('someoutputfile.csv', 'wb') as outfile:
for i, fname in enumerate(allFiles):
with open(fname, 'rb') as infile:
if i != 0:
infile.readline() # Throw away header on all but first file
# Block copy rest of file from input to output without parsing
shutil.copyfileobj(infile, outfile)
print(fname + " has been imported.")
C'est ça; shutil.copyfileobj
gère efficacement la copie des données, réduisant considérablement le travail de niveau Python pour analyser et resérialiser).
Cela suppose que tous les fichiers CSV ont le même format, codage, fins de ligne, etc., et l'en-tête ne contient pas de nouvelles lignes incorporées, mais si c'est le cas, c'est beaucoup plus rapide que les alternatives.
Devez-vous le faire en Python? Si vous êtes prêt à le faire entièrement dans Shell, tout ce que vous devez faire est d'abord cat
la ligne d'en-tête d'un fichier .csv d'entrée sélectionné au hasard dans merged.csv
avant d'exécuter votre one-liner:
cat a-randomly-selected-csv-file.csv | head -n1 > merged.csv
for f in *.csv; do cat "`pwd`/$f" | tail -n +2 >> merged.csv; done
Vous n'avez pas besoin de pandas pour cela, juste le simple module csv
fonctionnerait bien.
import csv
df_out_filename = 'df_out.csv'
write_headers = True
with open(df_out_filename, 'wb') as fout:
writer = csv.writer(fout)
for filename in allFiles:
with open(filename) as fin:
reader = csv.reader(fin)
headers = reader.next()
if write_headers:
write_headers = False # Only write headers once.
writer.writerow(headers)
writer.writerows(reader) # Write all remaining rows.
Voici une approche plus simple - vous pouvez utiliser pandas (bien que je ne sais pas comment cela aidera avec RAM utilisation) -
import pandas as pd
import glob
path =r'data/US/market/merged_data'
allFiles = glob.glob(path + "/*.csv")
stockstats_data = pd.DataFrame()
list_ = []
for file_ in allFiles:
df = pd.read_csv(file_)
stockstats_data = pd.concat((df, stockstats_data), axis=0)