Obecnie używam poniższego kodu, aby zaimportować 6000 plików CSV (z nagłówkami) i eksportuj je do jednego pliku CSV (za pomocą jednego wiersza nagłówka).

#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.")

Ten kod działa dobrze, ale jest powolny. Proces trwa do 2 dni.

Dostałem pojedynczy skrypt linii do linii poleceń terminalu, która robi to samo (ale bez nagłówków). Ten skrypt trwa 20 sekund.

 for f in *.csv; do cat "`pwd`/$f" | tail -n +2 >> merged.csv; done 

Czy ktoś wie, jak mogę przyspieszyć pierwszy skrypt Pythona? Ciąć czas w dół, pomyślałem o tym, że nie importuje go w dataframe i po prostu połączenia CSV, ale nie mogę tego zrozumieć.

Dzięki.

19
mattblack 28 czerwiec 2017, 01:58

4 odpowiedzi

Najlepsza odpowiedź

Jeśli nie potrzebujesz CSV w pamięci, po prostu kopiowanie z wejścia na wyjście, będzie dużo taniej, aby uniknąć analizowania parsowania, a kopii bez budowy w pamięci:

import shutil
import glob


#import csv files from folder
path = r'data/US/market/merged_data'
allFiles = glob.glob(path + "/*.csv")
allFiles.sort()  # glob lacks reliable ordering, so impose your own if output order matters
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.")

Otóż to; shutil.copyfileobj Skutecznie kopiowanie danych, dramatycznie Zmniejszenie pracy na poziomie Pythona do analizowania i respektyzacji.

Zakłada, że wszystkie pliki CSV mają ten sam format, kodowanie, zakończenia linii itp., A nagłówek nie zawiera osadzonych Newlines, ale jeśli tak jest, jest to dużo szybciej niż alternatywy.

20
thoomasbro 21 styczeń 2020, 18:16

Oto prostsze podejście - możesz używać pandy (choć nie jestem pewien, jak pomoże z wykorzystaniem RAM) -

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)
0
markroxor 6 maj 2019, 09:05

Nie potrzebujesz pandy, tylko proste csv moduł działałby dobrze.

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.
1
Alexander 27 czerwiec 2017, 23:34

Czy musisz to zrobić w Pythonie? Jeśli jesteś otwarty, aby wykonać to całkowicie w skorupie, wszystko, co musisz zrobić, to pierwszy cat wiersz nagłówka z losowo wybranego pliku wejściowego .CSV do merged.csv Przed uruchomieniem 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 
9
Peter Leimbigler 27 czerwiec 2017, 23:17