前回・前々回と、pandas.DataFrame の基礎編についての記事を書きましたが、
- Pandas の DataFrame の基本的な使い方 - akiyoko blog
- pandas.DataFrame の列の抽出(射影)および行の抽出(選択)方法まとめ - akiyoko blog
その応用編として、時系列データを扱うための手習いとして pandas.DataFrame をいろいろ弄ってみようと思っています。
なおこれまで同様、ローカルの実行環境は以下の通りとなっています。
- MacOS Sierra 10.12.3
- Python 2.7.12 (Anaconda 4.2.0)
- Jupyter Notebook 4.2.0
- pandas 0.18.1
まずは、import などの諸設定。
import glob import pandas as pd import matplotlib import matplotlib.pyplot as plt %matplotlib inline pd.options.display.max_rows = 10 plt.style.use('ggplot') font = {'family': 'IPAexGothic'} matplotlib.rc('font', **font)
CSVファイルからデータを読み込む
例えば、1日分のデータとして以下のような CSVデータを想定。
一列目(date)が日付なのですが、「yymmdd」形式で出力されています。
date,expected_value,preliminary_value,name,confirmed_value 160301,,,, 160301,0,-100,銀行券要因, 160301,-7200,-10000,財政等要因, 160301,-7200,-10100,資金過不足, 160301,6000,6000, , 160301,7500,7500, , 160301,,, , 160301,,, , 160301,,, , 160301,,, , 160301,,, , 160301,,, , 160301,,, , 160301,-300,-300, , 160301,-100,-100, , 160301,,, , 160301,,, , 160301,,, , 160301,,, , 160301,,-200, , 160301,+13100,+12900, , 160301,,, , 160301,,, , 160301,+0,+0, , 160301,+13100,+12900,合計, 160301,+5900,+2800,当座預金増減, 160301,,2592700,当座預金残高, 160301,,2336500, , 160301,,1896900, , 160301,,1896900, , 160301,,256200, , 160301,,,マネタリーベース, 160301,,積み期間(2/16~3/15日)の所要準備額(積数),積み期間(2/16~3/15日)の所要準備額(積数),1917300 160301,,積み期間(2/16~3/15日)の所要準備額(1日平均),積み期間(2/16~3/15日)の所要準備額(1日平均),66100 160301,,3/2日以降の残り要積立額(積数),3/2日以降の残り要積立額(積数),3300 160301,,3/2日以降の残り要積立額(1日平均),3/2日以降の残り要積立額(1日平均),200
まずは、CSVデータの読み込み。
CSV データの一列目の日付文字列を DatetimeIndex オブジェクトに変換して、index 列として読み込んでいます。
(参考)pandasで様々な日付フォーマットを取り扱う - Qiita
date_parser = lambda d: pd.datetime.strptime(d, '%y%m%d') df = pd.read_csv( '/Users/akiyoko/PycharmProjects/marketstat/downloads/boj/2016/160301.csv', index_col='date', parse_dates=True, date_parser=date_parser, na_values=' ', # たまに「name」列に ' ' が入っているので NaN に変換 ) df
na_values オプションは、CSV 読み込み時に特定の値(今回の場合は半角スペース)を NaN に変換してくれるので便利です。
特定の列が NaN の行を除外
「name」列や「preliminary_value」列が NaN の行を除外します(不要なので)。
(参考)http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html
df = df.dropna(subset=['name', 'preliminary_value']) df
特定条件の行だけを抽出
「name」列が「当座預金残高」になっている行だけを抽出します。
df = df[df['name'] == '当座預金残高'] df
特定の列だけを抽出
「expected_value」列と「confirmed_value」列を除外します(不要なので)。
(参考)http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop.html
df = df.drop(['expected_value', 'confirmed_value', 'name'], axis=1) df # 以下のように残すカラムだけ指定しても、同じ結果が得られる # df = df[['preliminary_value']]
ラベル名を変更
column名を「preliminary_value」から「当座預金残高」に変更します。
(参考)https://nkmk.github.io/blog/python-pandas-dataframe-rename/
df = df.rename(columns={'preliminary_value': u'当座預金残高'})
次に、index名を「Date」に変更します。
df.index.names = ['Date']
df
値を int型に変換
ここで、「当座預金残高」列のデータの値は object 型になっています。
df[u'当座預金残高']
Date 2016-03-01 2592700 Name: 当座預金残高, dtype: object
object型のままだとグラフにできないので、int型に変換します。
(参考)Python pandas strアクセサによる文字列処理 - StatsFragments
df[u'当座預金残高'] = df[u'当座預金残高'].astype(int) df[u'当座預金残高']
Date 2016-03-01 2592700 Name: 当座預金残高, dtype: int64
実践編
次に、一定期間分(2016〜2017年分)の CSVデータを読み込んでみます。
# 時系列データ(日銀の当座預金残高)を読み込む df_boj = pd.DataFrame() date_parser = lambda d: pd.datetime.strptime(d, '%y%m%d') paths = glob.glob('/Users/akiyoko/PycharmProjects/marketstat/downloads/boj/201[67]/*.csv') for path in paths: df = pd.read_csv(path, index_col='date', parse_dates=True, date_parser=date_parser, na_values=' ') # 「name」列や「preliminary_value」列が NaN の行を除外 df = df.dropna(subset=['name', 'preliminary_value']) # 「name」列が '当座預金残高' になっている行だけに絞る df = df[df['name'] == '当座預金残高'] # 「expected_value」列と「confirmed_value」列を除外 df = df.drop(['expected_value', 'confirmed_value', 'name'], axis=1) # column名を「preliminary_value」から「当座預金残高」に変更 df = df.rename(columns={'preliminary_value': u'当座預金残高'}) # index名を「Date」に変更する df.index.names = ['Date'] # object型のままだとグラフにできないので int型に変換 df[u'当座預金残高'] = df[u'当座預金残高'].astype(int) # 行を末尾に追加 df_boj = df_boj.append(df) # なお、column数が1つだけの場合はyオプションは不要 df_boj.plot() df_boj
ここで、2016年の時系列データ(日経平均株価)を読み込んでみます。
# 時系列データ(日経平均株価)を読み込む df_n225 = pd.read_csv('n225.csv', index_col='Date', parse_dates=True, usecols=['Date', 'Adj Close']) df_n225 = df_n225.sort_index() df_n225 = df_n225.rename(columns={'Adj Close': u'日経平均株価(終値)'}) df_n225.plot() df_n225
単純に、二つのグラフを同じ図上に表示してみます。
日経平均株価の値が相対的に小さすぎて、地を這うようなグラフになってしまいました。
ax = df_boj.plot() df_n225.plot(ax=ax)
見やすいように倍率を調整してみます。
adj = df_boj[u'当座預金残高'].mean() / df_n225[u'日経平均株価(終値)'].mean() ax = df_boj.plot() (df_n225 * adj).plot(ax=ax)
最後に、期間を合わせてみます。
start_date = '2016-01-01' end_date = '2016-12-31' span = pd.date_range(start_date, end_date) df_2016 = pd.DataFrame(index=span) df_2016 = df_2016.join(df_boj[start_date:end_date]) df_2016 = df_2016.join(df_n225[start_date:end_date] * adj) df_2016.plot() df_2016
参考
Pandas について本格的に勉強するならこちらの本を。
Jypyter Notebook の勉強をするならこの本を。