やりたいこと
- Pandas-DataReaderを使って、複数の株価データを取得し、各データをそれぞれ独立した変数に代入したい
- 相応の数のデータを取り扱うので、変数名をリスト化し、ループで処理したい(変数に代入する記述を1回にまとめたい)
- 上記を実現するために、動的に変数を呼び出して値を代入する方法を検討
結論
- データにラベルをつける必要がなければ、リストを使うのが楽
- 変数名に銘柄名などのラベルをつける必要があれば、globals()を使えば実現できる
- そもそも、同じような目的の質問はネットに多数存在するが、整理された手法が見当たらないところを見ると、実務ではこのような手法はあまり使われないのだろうと思う。必要なデータはさっさとデータベースに入れるとか、使うデータだけ、(ラベルもつけられる)DataFrameにまとめて格納するとか、別のやり方を目指した方が良さそう
変数を動的に生成するいくつかの手法
リストを使う
データにラベルをつけなくてよければリストを使うのが簡単。
取得したデータをリスト(以下の例では'data_list')に格納すれば、リストの番号でそれぞれのデータを識別できる。
リストに格納されたデータ
- data_list[0] → Nikkei225
- data_list[1] → DowJones
- data_list[2] → NASDAQ
import pandas_datareader as pdr
markets = (
'^NKX',#Nikkei225
'^DJI',#DowJones
'^NDQ'#NASDAQ
)
data_list = []
for market in markets:
data = pdr.DataReader(market, 'stooq', '2020-01-01', '2020-01-10')#DataReaderを使って、stooqというサイトから各マーケットの株価データを取得し、dataに格納
data_list.append(data)#dataに格納された各マーケットの株価データをdata_listに格納
print('data_list[0]:', data_list[0])#data_listの1つ目はNikke225
print('data_list[1]:', data_list[1])#data_listの2つ目はDowJones
print('data_list[2]:', data_list[2])#data_listの3つ目はNASDAQ
globals()を使う
11行目で、Nikkei225、DowJones、NASDAQと言う名前の変数に株価データが格納された。
15行目で各変数の中身を取り出しているが、ここで以下のように書くと、Nikkei225、DowJones、NASDAQという変数名が表示され、変数の中身が取り出せない。
print(name)
9行目でname変数に渡されたmarkets(リスト型)の値が表示される。
変数としてのnameの値(Nikkei225、DowJones、NASDAQなどの文字列)を変数名に持つ変数の中身(値)を表示することはprint()関数ではできないようだ。
そこでglobals()関数を使って、nameの値(Nikkei225など)を取り出してprint()に渡す。
print(globals())を実行すると
ループの初回(nameにNikkei225が代入されている状態)での出力結果。
'name'をkeyとして、その値'Nikkei225'を取り出してprint()に渡す、という処理が行われている。
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1089b0f10>, '__spec__': None, '__file__': '/Users/中略/dinamic_variables_dataframe.py', '__builtins__': <module 'builtins' (built-in)>, 'pdr': <module 'pandas_datareader' from '/Users/中略/pandas_datareader/__init__.py'>, 'markets': {'^NKX': 'Nikkei225', '^DJI': 'DowJones', '^NDQ': 'NASDAQ'}, 'market': '^NKX', 'name': 'Nikkei225'}
import pandas_datareader as pdr
markets = {
'^NKX':'Nikkei225',
'^DJI':'DowJones',
'^NDQ':'NASDAQ'
}
for market in markets:
name = markets[market]
globals()[name] = pdr.DataReader(market, 'stooq', '2020-01-01', '2020-01-10')
#結果を確認
print('name:',name)
print(globals()[name])
#一つずつ変数を指定して表示する場合は以下の記述で問題ない
print('Nikkei225:', Nikkei225)
print('DowJones:', DowJones)
print('NASDAQ:',NASDAQ)
(おまけ)データの取り出しはvars()でもできる
vars()は引数にとったプロパティの名前と対応する値を返すので、ここでは同じような使い方ができる。
(参考)vars()の解説
https://qiita.com/ganariya/items/e01e0355c78e27c59d41
exec()を使う
exec()を使う方法もネットでは割と見かけるが、代入する値が文字列や数字などであれば良いが、DataFrameのようなオブジェクト型は代入できないようなので採用せず。
参考にしたサイト
https://laboratory.kazuuu.net/create-dynamically-named-variables-from-user-input-in-python/
ソースコード(GitHub)
https://github.com/datascience-lab-xyz/blog/tree/master/dinamic-variables