note.nkmk.me

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

Date: 2016-05-04 / Modified: 2018-02-11 / tags: Python, pandas, スクレイピング
このエントリーをはてなブックマークに追加
スポンサーリンク

概要

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

以前はpandas.ioという名前でpandasの一部として提供されていたが、今はpandas-datareaderとして独立している。

インストール

pipでインストールできる。

$ pip install pandas-datareader

データソース

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変更により使えなくなったりするなど変更も多いので、最新情報は公式ドキュメントを参照。

株価(Morningstar)

v0.6.0からYahoo! Financeが使えなくなったので、代わりにMorningstarを使う。

ソニー(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')

Python pandas-datareader morningstar

最初の日で規格化。

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')

Python pandas-datareader morningstar normalized

人口、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()を使う。はじめのうちは世界銀行のサイトで検索するほうが取っ付きやすいと思う。

世界銀行のサイトで検索

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

で検索できる。検索窓から飛んだ先の個別ページ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()

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')
pandas datareader 人口
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事