web-dev-qa-db-ja.com

複数のcsvファイルを同じヘッダーを持つ単一のcsvに連結する-Python

現在、以下のコードを使用して、6,000個のcsvファイル(ヘッダー付き)をインポートし、それらを1つのcsvファイル(1つのヘッダー行)にエクスポートしています。

#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日かかる場合があります。

同じことを行うターミナルコマンドラインの1行のスクリプトが与えられました(ただし、ヘッダーはありません)。このスクリプトには20秒かかります。

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

私は最初のPythonスクリプトを高速化する方法を知っていますか? 。

ありがとう。

12
mattblack

入力から出力にコピーするだけで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ファイルが同じ形式、エンコーディング、行末などを持ち、ヘッダーに改行が埋め込まれていないことを前提としていますが、その場合、代替よりもはるかに高速です。

14
ShadowRanger

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 
6

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.
1
Alexander

より簡単なアプローチを次に示します-pandasを使用できます(ただし、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