pandas-datareaderで株価や人口のデータを取得

概要 pandas-datareaderを使うと、Web上の様々なソースに簡単にアクセスし、pandasのDataFrameの形でデータを取得できます。

pandas-datareader — pandas-datareader 0.6.0 documentation pydata/pandas-datareader

以前はpandas.ioという名前でpandasの一部として提供されていたが、今はpandas-datareaderとして独立しています。 インストール pipでインストールできます。

$ pip install pandas-datareader

インポートエラーが発生した場合の対処

2018年8月29日現在、pandasのバージョンが0.23.0以上だとインポート時にエラーが発生します。

ImportError: cannot import name 'is_list_like'

pandas-datareaderの次バージョン0.7.0では修正されるとのことだが、まだリリースされていません。

COMPAT: Add forward compat for is_list_like by bashtage · Pull Request #520 · pydata/pandas-datareader

GitHubから最新版をインストールすれば問題ありません。

$ pip install git+https://github.com/pydata/pandas-datareader.git

データソース

v0.6.0時点で、以下のソースがサポートされています。

Google Finance Morningstar IEX Robinhood Enigma Quandl St.Louis FED (FRED) Kenneth French’s data library World Bank OECD Eurostat Thrift Savings Plan Nasdaq Trader symbol definitions Stooq MOEX

Yahoo! FinanceがAPI変更により使えなくなったりするなど変更も多いので、最新情報は公式ドキュメントを参照。

Remote Data Access — pandas-datareader 0.6.0 documentation

株価(Morningstar)

v0.6.0からYahoo! Financeが使えなくなったので、代わりにMorningstarを使います。 ※2018年8月29日時点でMorningstarも使えなくなっています。上述のデータソースの公式ドキュメントなどを参考に使用可能なデータソースに変更する必要があります。2018年8月29日時点ではIEXは使えているので以下のサンプルコードのmorningstarの部分をiexに置換すれば問題ありません。 例 ソニー(SNE)の株価情報を取得してみます。なお、米Morningstarからのデータなので、ニューヨーク証券取引所(NYSE)での株価で単位はドルとなります。

import pandas_datareader.data as web
import datetime
import matplotlib.pyplot as plt

start = datetime.datetime(2012, 1, 1)
end = datetime.datetime(2017, 12, 31)

f = web.DataReader('SNE', 'morningstar', start, end)

print(f.head())
#                    Close   High    Low   Open   Volume
# Symbol Date                                           
# SNE    2012-01-02  18.04  18.04  18.04  18.04        0
#        2012-01-03  18.38  18.50  18.28  18.28  1414748
#        2012-01-04  18.22  18.27  18.14  18.24  1146367
#        2012-01-05  17.70  17.85  17.60  17.83  1464843
#        2012-01-06  17.44  17.57  17.37  17.57   594057

web.DataReader(name, data_source, start, end)の引数は以下のとおりです。

name : データセットの名前。ティッカーシンボルを指定します。strまたはlist。 GOOG, AAPL, MSFTなど。 日経平均(^N225)やダウ平均(^DJI)も。

data_source : データソースの名前。 Google Financeからデータを取得したい場合は'google'とします。

start : 取得したい期間の開始日時、datetime型で指定します。 end : 取得したい期間の終了日時、datetime型で指定します。

Morningstarの場合、取得できるデータは5項目。

Open : 始値 High : 高値 Low : 安値 Close : 終値 Volume: 出来高

複数のデータを同時に取得

ティッカーシンボルを指定するnameはリストも可能。ソニーとアップルの値を同時に取得してみます。 nameをリストにすると、マルチインデックスのpandas.DataFrameでデータが取得できます。

f2 = web.DataReader(['SNE', 'AAPL'], 'morningstar', start, end)

print(type(f2.index))
print(f2.head())
print(f2.tail())
# <class 'pandas.core.indexes.multi.MultiIndex'>
#                    Close   High    Low   Open   Volume
# Symbol Date                                           
# SNE    2012-01-02  18.04  18.04  18.04  18.04        0
#        2012-01-03  18.38  18.50  18.28  18.28  1414748
#        2012-01-04  18.22  18.27  18.14  18.24  1146367
#        2012-01-05  17.70  17.85  17.60  17.83  1464843
#        2012-01-06  17.44  17.57  17.37  17.57   594057
#                     Close    High      Low    Open    Volume
# Symbol Date                                                 
# AAPL   2017-12-25  175.01  175.01  175.010  175.01         0
#        2017-12-26  170.57  171.47  169.679  170.80  33185536
#        2017-12-27  170.60  170.78  169.710  170.10  21498213
#        2017-12-28  171.08  171.85  170.480  171.00  16480187
#        2017-12-29  169.23  170.59  169.220  170.52  25999922

比較したい場合はunstack()メソッドでピボットしたほうが処理しやすいです。

f2_u = f2.unstack(0)
print(f2_u.head())
#               Close            High             Low            Open         \
# Symbol         AAPL    SNE     AAPL    SNE     AAPL    SNE     AAPL    SNE   
# Date                                                                         
# 2012-01-02  57.8571  18.04  57.8571  18.04  57.8571  18.04  57.8571  18.04   
# 2012-01-03  58.7471  18.38  58.9286  18.50  58.4286  18.28  58.5000  18.28   
# 2012-01-04  59.0629  18.22  59.2400  18.27  58.4686  18.14  58.6000  18.24   
# 2012-01-05  59.7186  17.70  59.7929  17.85  58.9529  17.60  59.2786  17.83   
# 2012-01-06  60.3429  17.44  60.3929  17.57  59.8886  17.37  59.9671  17.57   
#               Volume           
# Symbol          AAPL      SNE  
# Date                           
# 2012-01-02         0        0  
# 2012-01-03  75564699  1414748  
# 2012-01-04  65061108  1146367  
# 2012-01-05  67816805  1464843  
# 2012-01-06  79596412   594057  

print(f2_u['Close'].head())
# Symbol         AAPL    SNE
# Date                      
# 2012-01-02  57.8571  18.04
# 2012-01-03  58.7471  18.38
# 2012-01-04  59.0629  18.22
# 2012-01-05  59.7186  17.70
# 2012-01-06  60.3429  17.44

プロット

プロットするのも簡単。

f2_u['Close'].plot(title='SNE vs AAPL', grid=True)
# plt.show()
plt.savefig('data/dst/pandas_datareader_morningstar.png')

最初の日で規格化。

f2_u['Close', 'AAPL'] /= f2_u['Close'].loc[f2_u.index[0], 'AAPL']
f2_u['Close', 'SNE'] /= f2_u['Close'].loc[f2_u.index[0], 'SNE']

f2_u['Close'].plot(title='SNE vs AAPL', grid=True)
# plt.show()
plt.savefig('data/dst/pandas_datareader_morningstar_normalize.png')

人口、GDPなど(World Bank) 例 世界銀行が公開している人口、GDP、出生率などのマクロデータにアクセスできます。 日本とアメリカの人口を取得してみます。

from pandas_datareader import wb

f = wb.download(indicator='SP.POP.TOTL', country=['JP', 'US'],
                start=1960, end=2014)
print(f)
#                     SP.POP.TOTL
# country       year             
# Japan         2014    127276000
#               2013    127445000
#               2012    127629000
#               2011    127833000
#               2010    128070000
# ...                         ...
# United States 1989    246819000
#               1988    244499000
#               1987    242289000
# ...                         ...
#               1962    186538000
#               1961    183691000
#               1960    180671000
# [110 rows x 1 columns]


wb.download(indicator, country, start, end)の引数は以下のとおりです。

indicator : データのID。後述。 country : 国名。strまたはlist。 ISO 3166-1で定められた、2文字または3文字の国名コード。 start : 取得したい期間の開始年。int。 end : 取得したい期間の終了年。int。

indicator

indicatorで指定するIDは世界銀行のサイトで検索するか、wb.search()を使います。はじめのうちは世界銀行のサイトで検索するほうが取っ付きやすいと思います。

世界銀行のサイトで検索

世界銀行のサイトで検索する場合、

Indicators | Data

で検索できます。検索窓から飛んだ先の個別ページURLの末尾がIDとなります。 例えば、CO2排出量の場合、検索窓に「CO2」と入力するといくつか候補が挙げられるので、「CO2 emissions (kt)」を選んで「Go」をクリックすると、個別ページが表示される。IDは個別ページのURL(http://data.worldbank.org/indicator/EN.ATM.CO2E.KT)の末尾、'EN.ATM.CO2E.KT'となります。 主要な指標は「Indicators | Data」の下の方に列挙されているので、そこから選んでもよい。

wb.search()を使うとPython上でIDを検索できます。 例えば、per capita(一人あたり)、constant dollarsのGDPのIDを知りたい場合、引数に正規表現の文字列'gdp.*capita.*const'を入れます。 idと名前(簡単な説明)が表示されるので、所望のIDを選びます。

print(wb.search('gdp.*capita.*const').iloc[:, :2])
#                         id                                               name
# 685     6.0.GDPpc_constant  GDP per capita, PPP (constant 2011 internation...
# 8086        NY.GDP.PCAP.KD                 GDP per capita (constant 2010 US$)
# 8088        NY.GDP.PCAP.KN                      GDP per capita (constant LCU)
# 8090     NY.GDP.PCAP.PP.KD  GDP per capita, PPP (constant 2011 internation...
# 8091  NY.GDP.PCAP.PP.KD.87  GDP per capita, PPP (constant 1987 internation...

慣れないうちはちょっと難しい。

プロット

wb.download()で取得できるデータは階層型のマルチインデックスとなっています。

#                     SP.POP.TOTL
# country       year             
# Japan         2014    127276000
#               2013    127445000
#               2012    127629000
#               2011    127833000
#               2010    128070000
# ...                         ...
# United States 1989    246819000
#               1988    244499000
#               1987    242289000
# ...                         ...
#               1962    186538000
#               1961    183691000
#               1960    180671000
# [110 rows x 1 columns]

グラフにプロットしたい場合などはこのままだと使いにくいので、unstack()を使い行から列へピボットします。

f = wb.download(indicator='SP.POP.TOTL', country=['JP', 'US'],
                start=1960, end=2014)
f2 = f.unstack(level=0)
print(f2)
#         SP.POP.TOTL              
# country       Japan United States
# year                             
# 1960       92500572     180671000
# 1961       94943000     183691000
# 1962       95832000     186538000
# 1963       96812000     189242000
# 1964       97826000     191889000
# ...                           ...
# 2010      128070000     309348193
# 2011      127833000     311663358
# 2012      127629000     313998379
# 2013      127445000     316204908
# 2014      127276000     318563456

'SP.POP.TOTL'が邪魔なので、columnsをリネームしてプロットします。

f2.columns = ['Japan', 'United States']
f2.plot(grid=True)
# plt.show()
plt.savefig('data/dst/pandas_datareader_wb.png')
Last Updated: 6/26/2019, 10:34:03 PM