2017-10-10 15 views
0

50行と15列の50個のcsvファイルから2つの列を持つデータフレームを構築しようとしています。 concat関数を使わずに実行しようとすると、メモリが大量に消費され、killエラーが発生します。今私はデータベースをチャンクして、それを連結しています。唯一の問題は、チャンクを連結すると、各チャンクのヘッダーが保持され、dfのhead()を出力すると、最後のチャンクの先頭行が得られます。そして、私のコードをもっと速く動かすための他の方法があります。私はforループでconcat関数を使って読むほうが遅くなります。私のコードは次のようになります: -concat関数を使用してPython3で大規模なCSVファイルを処理する

import os 
import csv 
import urllib.request as urllib 
import datetime as dt 
import pandas as pd 
import pandas_datareader.data as web 
import nsepy as nse 

def saveNiftySymbols(): 
    url = "https://www.nseindia.com/content/indices/ind_nifty50list.csv" 
# pretend to be a chrome 47 browser on a windows 10 machine 
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"} 
    req = urllib.Request(url, headers = headers) 
# open the url 
    x = urllib.urlopen(req) 
    sourceCode = x.read().decode('utf-8') 

    cr = csv.DictReader(sourceCode.splitlines()) 
    l = [row['Symbol'] for row in cr] 
    return l 

def symbolToPath(symbol, path='/Users/uditvashisht/Documents/udi_py/stocks/stock_dfs/'): 
    return os.path.join(path,"{}.csv".format(str(symbol))) 

def combinedNifty(l): 
    mainDf=pd.DataFrame() 

    for symbol in l: 
     chunks=pd.read_csv(symbolToPath(symbol),chunksize=10,usecols=['Date','Close'],index_col='Date',parse_dates=True) 
     df=pd.DataFrame() 
     for chunk in chunks: 
      df=pd.concat([chunk]) 

      df.rename(columns={'Close':symbol}, inplace=True) 


     if mainDf.empty: 
      mainDf = df 
     else: 
      mainDf = mainDf.join(df, how='outer') 

    print(mainDf.head()) 
    mainDf.to_csv('combinedNifty.csv') 


combinedNifty(saveNiftySymbols()) 

答えて

0

唯一の問題、私はチャンクをCONCATとき、それは各チャンクのヘッダ を保持していることであると私はDFのために頭を()印刷するとき、それは私を提供 最後のチャンクの先頭行

これは実際に起こっていることは、あなたのdfに最後のチャンクしかないからです。

df=pd.concat([chunk]) 

実際には現在のチャンクのみを連結して再定義しています。これは効果的です:

For chunk in chunks: 
    df = chunk 

これは、head()メソッドを呼び出すときに、その最後のチャンクしか表示されないためです。代わりに、チャンクを連結するためのforループは必要ありません。 CONCATは、引数としてデータフレームのリストを受け取り、それらを一緒に連結するので、あなただけ実行する必要があります。多くのデータフレームのリストで一度CONCAT代わりにやった方がよいので、これもパフォーマンスを向上させる必要があります

df = pd.concat(chunks) 

forループにdf = pd.concat([df、chunk])のようなものがあります。元のコードで意図したとおりです。

+0

こんにちは、私はあなたの方法を使用し、それはチャンクの代わりに、リスト内の個々のシンボルの完全なデータフレームを取得するのに役立ちました。しかし、もし私が上記のコードを使って50のCSVファイルからデータフレームを作成し、それらに結合するのであれば、まだです。私はエラーを殺害している:9。 –

+0

あなたのすべてのデータフレームをマージするためにjoinの代わりに 'pd.merge'を使うには、[here](https://stackoverflow.com/questions/38089010/merge-a-list-of-pandas-dataframes)にあるアプローチを試してみてくださいdf.joinを繰り返し呼び出すのではなく、forループの外側に移動します。私は結合がconcatと同じ問題を持っているのかどうかは分かりませんが、thingsを改善するかもしれません。空リストを作成し、 'l:'のシンボルのそれぞれのリストに 'df'を追加してください。また、csvを読み込む際にメモリエラーを減らすために[この方法](https://stackoverflow.com/questions/17557074/memory-error-when-using-pandas-read-csv)をチェックしてください。 –

+0

また、なぜこのような小さなチャンクサイズを使用してcsvを処理しているのかわかりません。大規模なcsvをチャンクで処理する場合、[この記事(https://stackoverflow.com/questions/25962114/how-to-read-a-6-gb-csv-file-with-pandas)を参照してください。このコメントでは、forループではなくリストでconcatを呼び出す利点についても説明しています。 –

関連する問題