第2回 データを整える 〜S◯I証券風のチャートを描いてみる〜
今回は、Yahoo!ファイナンスのサイトからスクレイピングして、取得してきたデータを整えようと思います。
データを整えるとは??
データをコンピュータにも読み込める形にするということです。
データを取得したら、次はそれを使ってグラフを描いたり、計算したり・・・
いろいろできますよね!
でも、例えば、string型のデータを計算させることはできませんよね。
グラフとしてプロットするにも、int型などの然るべき型にしないといけません。
だから今回は、データを加工する前の必須工程である「データを整える」をやろうと思います。
前回は、Yahoo!ファイナンスからデータを取得するところまでやりました。
じゃあ、前回集めたデータは何がいけないのかを見てみます。
前回使ったソースコードで、Yahoo!ファイナンスから40日分の株価を取得しました。
問題点が2つあります。
1つは、インデックスがされてないことです。
左端の数字はインデックスなので、本来は0から順番に振られていないといけないのにも関わらず、0〜19でループしています。
これはデータの取得元のサイトのページ構造に原因があるので、こうなってしまうのは仕方がないことです。
なので、これは自分でインデックスを振りなおしてやる必要があります。
2つめは、日付が2016年8月1日となっていることです。
年とか月とは日は、コンピュータには読めません。
string型として入っているので、このままではグラフを作るさいに軸として使えません。
日付はx軸として使うので、なんとかしないとダメですね。
この2つの問題を解決するためのコードがこちらです。
import pandas import datetime def scraping_yahoo(code, start, end, term): base = "http://info.finance.yahoo.co.jp/history/?code={0}.T&{1}&{2}&tm={3}&p={4}" start = str(start) start = start.split("-") start = "sy={0}&sm={1}&sd={2}".format(start[0], start[1], start[2]) end = str(end) end = end.split("-") end = "ey={0}&em={1}&ed={2}".format(end[0], end[1], end[2]) page = 1 result = [] while True: url = base.format(code, start, end, term, page) df = pandas.read_html(url, header=0) if len(df[1]) == 0: break result.append(df[1]) page += 1 result = pandas.concat(result) result.columns = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close'] return result def generate(data): data_frame = data[["Date","Open","Close","High","Low",'Adj Close',"Volume",]] hiduke = pandas.DataFrame(data_frame["Date"]) hiduke.columns = ["Hiduke"] dates = [] for day in data_frame["Date"]: day = day.replace("年", "-") day = day.replace("月", "-") day = day.replace("日", "") time = datetime.datetime.strptime(day, '%Y-%m-%d') dates.append(time) data_frame["Date"] = dates tmp = data_frame["Date"].values.astype("datetime64[D]") d = tmp data_frame["Date"] = tmp.astype(float) index = len(data_frame["Date"]) index_data = [] for x in range(index): index_data.append(x) data_frame.index = index_data hiduke.index = index_data data_frame = pandas.concat([data_frame, hiduke], axis=1) return data_frame if __name__ == "__main__": company = 4312 EndDate = datetime.date.today() StartDate = EndDate - datetime.timedelta(days=60)#640 data = scraping_yahoo(company, StartDate, EndDate, "d") print(data) generate_data = generate(data) print(generate_data)
前回のコードにプラスしているので、少し長くなっています。
新しくなっているコードはdef generate(data):の部分です。
このコードを実行することでデータがこうなります。
インデックスが整っています。
日付であるDateが変換されていますね。
これは、Dateをdatetime64という形式にしてから、さらにfloatの型にはめ込んだためです。
なぜこの型なのかというと、私はこのあとにmatplotlib.financeというモジュールで、ローソク足をプロットします。
モジュールの関数が、この形だと扱いやすかったのでこうしました。
しかし、これだと本当の日付がわからないので、本来の年月日の日付もHidukeとして追加して、残しています。
ここからはコードを解説したいと思います。
もう一度、今回新しくなった部分のコードを貼りますね。
def generate(data): data_frame = data[["Date","Open","Close","High","Low",'Adj Close',"Volume",]] hiduke = pandas.DataFrame(data_frame["Date"]) hiduke.columns = ["Hiduke"] dates = [] for day in data_frame["Date"]: day = day.replace("年", "-") day = day.replace("月", "-") day = day.replace("日", "") time = datetime.datetime.strptime(day, '%Y-%m-%d') dates.append(time) data_frame["Date"] = dates tmp = data_frame["Date"].values.astype("datetime64[D]") d = tmp data_frame["Date"] = tmp.astype(float) index = len(data_frame["Date"]) index_data = [] for x in range(index): index_data.append(x) data_frame.index = index_data hiduke.index = index_data data_frame = pandas.concat([data_frame, hiduke], axis=1) return data_frame
まずはじめに、引数をdataにし、scraping_yahooのreturnを受け取っています。
受け取ったデータをそのまま、data_frameに入れています。
次に、hidukeという新しいデータフレームを作っています。
そして、その中には受け取ったデータであるdata_frameの["Date"]をそのまま入れています。
columnsの名前をHidukeにしました。
今から、日付の年月日をいじるのですが、元のデータも残しておきたいのです。
そのため、hidukeというデータフレームを作って避難させています。
下がそのコードです。
data_frame = data[["Date","Open","Close","High","Low",'Adj Close',"Volume",]] hiduke = pandas.DataFrame(data_frame["Date"]) hiduke.columns = ["Hiduke"]
ここからdata_frameのDateの年月日をいじっていこうと思います。
2016年8月1日という形から、2016-8-1という形に変換しています。
この形だと、datetimeモジュールの形式に合うので、加工しやすくなります。
加工したデータは、リストであるdates = []に入っています。
そのため、そのままdata_frame["Date"] = datesで上書きしてやればOKです。
普通はここまでで良いかもしれません。
私の場合は、このデータをローソク足をプロットする際に使うため、もう少しデータの形式を変える必要があります。
ここからさらにdatetime64[D]という形式に変換しています。
そして、それをfloat型にしています。
日付の整形はこんなところです。
下がそのコードです。
dates = [] for day in data_frame["Date"]: day = day.replace("年", "-") day = day.replace("月", "-") day = day.replace("日", "") time = datetime.datetime.strptime(day, '%Y-%m-%d') dates.append(time) data_frame["Date"] = dates tmp = data_frame["Date"].values.astype("datetime64[D]") d = tmp data_frame["Date"] = tmp.astype(float)
次にインデックスです。
これは非常にシンプルで、len()でデータの数を調べます。
そして、データの数の分だけのリストを作ります。
それを.indexで上書きしてやるだけでOKです。
下がそのコードです。
index = len(data_frame["Date"]) index_data = [] for x in range(index): index_data.append(x) data_frame.index = index_data hiduke.index = index_data
最後に忘れていはいけないのが、hidukeをくっつける作業です。
pandas.concatで2つのデータフレームを合体させています。
下がそのコードです。
data_frame = pandas.concat([data_frame, hiduke], axis=1) return data_frame
以上でデータが整いました。
今回はこんなところで終わろうと思います。
この作業は、少し面倒ですが必須工程です。
私の感覚からすると、この工程で一番時間がとられているようにも思います。
データが揃ってしまえば、あとの作業は楽しいですし、そもそもちゃんと使いやすいデータになっていれば作業が捗ります。
大変ですが、がんばりましょう笑
このデータで、私はローソク足を描いています。
ローソク足を書くにはもうひと頑張りいりますが、気になる方は見てみてください。
ちなみに続きはこちらです。