日々の学びと煩悩

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)の識別子だから、データフレームの中身ではない



(蛇足)識別子は厄介

wimper-1996.hatenablog.com

> 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_vvaluevで取り出すことができる