pandasを使用して複数のzipファイルに格納されているtickデータ(CSVファイル)から1時間足を作成する
「pythonを使用して所定のフォルダを再帰的に探索して、複数のzipファイルに格納されているCSVファイルだけを読み込む」で実施したこと、「pandasを使用してtickデータからOpen,High,Low,Closeデータを作成する」で実施したことを踏まえてタイトルに書いたことを実現した。
ソースは次。
※)実行速度に大きな問題があるが、その点は解決していないことに注意。今後の課題。
#coding:utf-8 import zipfile import os import glob import cStringIO import re import pandas as pd #Input inputFileDirName = 'input' inputFiles = os.listdir(inputFileDirName) #Data Processing flag = 0 g = os.walk(inputFileDirName) for dirpath, dirs, files in g: print dirpath, files for targetZipFile in glob.glob(dirpath+"/"+"*.zip"): #globを使用して、dirpathの中で拡張子がzipのものだけを取得 print targetZipFile unzippedZf = zipfile.ZipFile(targetZipFile, 'r') #zipファイル解凍 fileListInZip = unzippedZf.namelist() #zipファイル内のファイルリスト取得 for fileName in fileListInZip: if(re.compile("USDJPY.csv").search(fileName)): #拡張子がcsvのものを対象とする(「.csv」を含むファイルが拡張子がcsvのものしかないことが前提) print fileName inFile = cStringIO.StringIO(unzippedZf.read(fileName)) #cStringIOを使用して、zipファイルを展開せずにメモリ上で読み込む outFile = cStringIO.StringIO() count = 0 for line in inFile: if count==0: #元ファイルのヘッダをスキップする #outFile.write(line) count += 1 continue count += 1 outFile.write(line.replace(line[:3],"\"20"+line[1:3])) #簡潔な方法が分からなかったので、とりあえず泥臭くても良いから実装 outFile.seek(0) #ファイルの先頭から読み込みたいため、ファイルの先頭バイトへ戻す df = pd.read_csv(outFile, sep=',', names=('Date','Pair', 'Bid', 'Ask',''), parse_dates=True, float_precision = "high", ) print df #IndexをdateTimeIndexに変換 dateTimeIndex = pd.DatetimeIndex(df.iloc[:,0]) df.index = dateTimeIndex print df bidSeries = df.iloc[:,2] askSeries = df.iloc[:,3] bidOHLC = bidSeries.resample('H', how='ohlc') askOHLC = askSeries.resample('H', how='ohlc') if flag==0: flag = 1 bidOHLC_outputFrame = bidOHLC askOHLC_outputFrame = askOHLC else: bidOHLC_outputFrame = pd.concat([bidOHLC_outputFrame, bidOHLC]) askOHLC_outputFrame = pd.concat([askOHLC_outputFrame, askOHLC]) #Write Data to Csv bidOHLC_outputFrame.to_csv("bidOHLC.csv") askOHLC_outputFrame.to_csv("askOHLC.csv")
大きくハマった所は次の1文を忘れていた所。
outFile.seek(0)#ファイルの先頭から読み込みたいため、ファイルの先頭バイトへ戻す
これを実行せずにStringIOからデータを読み込めずに非常に困った。
「pandas unable to read from large StringIO object」を見て解決。
もう1つ言えば、pandas.read_csvの仕組みが今一歩分かっていない。
今回はとりあえずやっつけで実施している部分もある。
下記部分。
df = pd.read_csv(outFile, sep=',', names=('Date','Pair', 'Bid', 'Ask',''), parse_dates=True, float_precision = "high", ) print df #IndexをdateTimeIndexに変換 dateTimeIndex = pd.DatetimeIndex(df.iloc[:,0]) df.index = dateTimeIndex print df
これを実行すると、1つめのprint文で下記が出力される。
Date Pair Bid Ask
0 2015/05/01 06:10:03.765 USD/JPY 119.400 119.420 NaN
1 2015/05/01 06:10:04.266 USD/JPY 119.400 119.420 NaN
2 2015/05/01 06:10:04.767 USD/JPY 119.400 119.420 NaN
・・・・・・
「NaN」が出力されるのは、「,」区切りでCSVを読み込んで、行末が改行となっているからだと思う。
2つ目のprint文では下記が出力される。
Date Pair Bid Ask \
2015-05-01 06:10:03.765 2015/05/01 06:10:03.765 USD/JPY 119.400 119.420
2015-05-01 06:10:04.266 2015/05/01 06:10:04.266 USD/JPY 119.400 119.420
・・・・・・・・・・・・
日付が2列あり、read_csvでのnamesの付け方でずれたりしたので、この辺の理解が曖昧。
今後の課題とする。
もう1つは、前回「pythonのpandas.datetime.strptimeでは「YY/MM/dd」日付を表す文字列をdatetimeに変換できない?」で書いた、「YY/MM/dd」形式だと「dateTimeIndex = pd.DatetimeIndex(df.iloc[:,0])」で日付が正常に変換されなかった点。
「YYYY/MM/dd」に変換してから「dateTimeIndex = pd.DatetimeIndex(df.iloc[:,0])」を実行しなければならない。