for文で変数名を取得する
やりたかったこと
複数のデータフレームを新たに定義し、作成した時(df_ex1, df_ex2...)、最終的にそれらのデータフレームの辞書を作成したい。
こんな感じ↓
df_dict = {'df_ex1': (df_ex1の中身), 'df_ex2': (df_ex2の中身)...}
そのために、
データフレームの変数名('df_ex1', 'df_ex2'...) を次々とfor文で取り出したい
# 準備 # なんか適当に2つのデータフレームを作る > df_ex1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'data1': np.arange(4)}) > df_ex1 key data1 0 A 0 1 B 1 2 C 2 3 D 3 > df_ex2 = pd.DataFrame({'key': ['X', 'Y', 'Z'], 'data2': np.random.randn(3)}) > df_ex2 key data2 0 X -0.237526 1 Y -1.585649 2 Z 1.106063
(やり方)
ローカル変数の一覧を辞書として返す組み込み関数locals()
と、異なるオブジェクトのラベルを表す識別子id()
を利用する
> for df in [df_ex1, df_ex2]: df_val_k = [k for k, v in locals().items() if id(v) == id(df)] df_val_v = [v for k, v in locals().items() if id(v) == id(df)] print(df_val_k) print(df_val_v[0]) print('-------') # 結果 ['df_ex1', 'df'] key data1 0 A 0 1 B 1 2 C 2 3 D 3, ------- ['df_ex2', 'df'] key data2 0 X -1.738926 1 Y 0.573350 2 Z -0.403480
df_val_k[0]としてあげれば、データフレームの変数名が取得できる
さてここで、間違い↓
> for df in [df_ex1, df_ex2]: df_val_k = [k for k, v in locals().items() if id(k) == id(df)] df_val_v = [v for k, v in locals().items() if id(k) == id(df)] print(df_val_k) print(df_val_v) print('----') # 結果 [] [] ---- [] []
何もなくなる
id(k) == id(df)
と一致するものがなかったということ
何をやってるのか
そもそもlocals()
で取得されるローカル変数の辞書は、
- key:変数名
- value:変数の中身
となっている。
id(k)
はつまり、データフレームの名前(key)の識別子だから、データフレームの中身ではない
(蛇足)識別子は厄介
> for df in [df_ex1, df_ex2]: print(locals().keys()) # 結果 dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__builtin__', '__builtins__', '_ih', '_oh', '_dh'......)
なんか色々混じっているが、これらは全て「キー」であって中身ではない。
if id(v) == id(df)
の条件部分では、
for文で取り出しているデータフレームの「中身」の識別子が一致するかどうかを条件としなくてはならない。
つまりlocals().keys()
のidではなくて
locals().values()
のidがdf
のidと等値かどうか
そして最後、
データフレームの変数名df_val_k
はキーk
で取り出し、
逆に変数の中身(データフレーム)df_val_v
はvaluev
で取り出すことができる