Объединение нескольких файлов csv в один csv с тем же заголовком - Python

В настоящее время я использую приведенный ниже код для импорта 6 000 csv файлов (с заголовками) и экспорта их в один файл csv (с одной строкой заголовка).

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

Этот код работает нормально, но он медленный. Это может занять до 2 дней.

Мне была предоставлена ​​одна строка script для командной строки терминала, которая делает то же самое (но без заголовков). Этот script занимает 20 секунд.

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

Кто-нибудь знает, как я могу ускорить первый Python script? Чтобы сократить время, я подумал о том, чтобы не импортировать его в DataFrame и просто конкатенации CSV, но я не могу понять это.

Спасибо.

Ответ 1

Если вам не нужен CSV в памяти, просто копирование с ввода на вывод, будет намного дешевле вообще избежать разбора и копировать без накопления в памяти:

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

Это; shutil.copyfileobj эффективно копирует данные, значительно сокращая работу на уровне Python для анализа и повторной инициализации.

Предполагается, что все CSV файлы имеют одинаковый формат, кодировку, окончания строк и т.д., А заголовок не содержит встроенных символов новой строки, но в этом случае он намного быстрее, чем альтернативы.

Ответ 2

Вам нужно сделать это в Python? Если вы открыты для этого полностью в оболочке, все, что вам нужно сделать, это сначала cat строка заголовка из случайно выбранного входного файла .csv в merged.csv перед запуском вашей однострочной линии:

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 

Ответ 3

Для этого вам не нужен pandas, просто простой модуль csv будет работать нормально.

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.

Ответ 4

Здесь более простой подход - вы можете использовать панд (хотя я не уверен, как это поможет с использованием оперативной памяти) -

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)