wellwell3176
@wellwell3176

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

pythonでエクセルに格納された各シートから辞書を作成したい

解決したいこと

pythonでエクセルに格納された各シートから辞書を作成したい

image.png

上図のような「各シートにkeyとvalueが入力されたエクセルファイル」から、

作りたいもの
dict_time = {"昼":0, "夜":1}
dict_position = {"課長"0,"新人":1 ……以下略

このようにdict_{各シート名}={key:value} の辞書を作り、

image.png

別に用意されたこのようなDataFrameの値を数値に変換したい。

辞書さえあれば、Dataframeの値を変換することはできるのですが、辞書が上手く作れなくて困っています。

発生している問題・エラー

まず、「シート名を取得してdict_{シート名}という関数を作る」ということを試しましたが、上手く行きませんでした。

dict_"{}".format("time") = {A:1,B:2}

>>> SyntaxError: invalid syntax

文字列から変数を作る、という処置はこういう風にはできない、というところで止まりました。

次に、変数名が作れないなら{シート名:{key:value}}のような多層構造の辞書を作ることを考えました。

import pandas as pd

#sheet_name = Noneとして全シート名を取得
dictionary = pd.read_excel(workdir +"/dict_raw.xlsx",sheet_name=None)

for i in dictionary:
  for n in range(len(dictionary[i])):
    setting.update({i:{dictionary[i]["key"][n]:dictionary[i]["value"][n]}})

上記の作業でsettingという1個の辞書に、{シート名:{key:value}}をどんどん詰め込もうとしたのですが、

print(setting)

>>>{'time': {'夜': 1}, 'position': {'新人': 3}, ・・・以下略}

このやり方だと辞書のkeyがsheet名として重複してしまうため、最後の1行しか保存してくれません。
重複しないように{{シート名:key}:value}という形にしようと思うと、

TypeError: unhashable type: 'dict'

のエラーで実装不可能です。
また、この辞書を使って逆変換も行いたい(※)のですが、{シート名:key}を組にするとそれが難しい気がします。

※ファイルを読み込んだ時に昼を0に変換するが、処理が終わってファイルを書き出すときには0を昼に戻したい、という意味

なにかいい方法があれば、どうぞよろしくお願いいたします。

補記

今の所、完全に力技ですが、下記のようにシート名を直打ちでなんとかしている状態です。

import pandas as pd

#sheet_name = Noneとして全シート名を取得
dictionary = pd.read_excel(workdir +"/dict_raw.xlsx",sheet_name=None)
dict_time = pd.read_excel(workdir +"/dict_raw.xlsx",sheet_name="time",index_col=0)
dict_time= dict(zip(dict_time.index,dict_time["value"]))

print(dict_time)

>>>{'昼': 0, '夜': 1}

#これをシート名の数だけ作る

1

2Answer

これで大丈夫ですかね?

import pandas as pd

dictionary = pd.read_excel(workdir +"/dict_raw.xlsx",sheet_name=None)
setting = {k: dict(v.to_numpy()) for k, v in dictionary.items()}
1Like

「シート名を取得した後、そのシート名を使って動的に変数(辞書)を作成したい」ということだと解釈しました。間違っていたらごめんなさい。

シート名とキーと値自体はpandasやopenpyxlなどで取得済みだと仮定します。この場合、以下のようなコードで実現自体は可能です。

sheet_name = "time"
key1 = ""
value1 = 0
key2 = ""
value2 = 1
# 以上は取得済みと仮定

exec("dict_{} = dict({}={}, {}={})".format(sheet_name, key1, value1, key2, value2))
print(dict_time)
出力
{'昼': 0, '夜': 1}

また、上の文章ではそのままdict_timeと入力していますが、呼び出し自体も何とかできないことはないです。

exec("print(dict_{})".format(sheet_name))
出力
{'昼': 0, '夜': 1}

一々処理をする度にこの記述をするのが面倒なようであれば、

exec("dict_to_process = dict_{}".format(sheet_name))

などのコードを用意すると、以降はdict_to_processとして変数を呼び出し可能です。

ここで使っているexecは組み込み関数の1つで、文字列をPython文として解釈してくれます。

ただ、「Python 変数 動的」などで検索してもらうとわかるのですが、このやり方は推奨されていません。

私自身は動的に変数名を設定することについて深く考察したことがないので、あまり断言はできません。ただ、呼び出すにしても、中のデータを弄るにしても、ひと手間かかりそうです。また、上のサイトを見る限り、変数のスコープもどうなるか怪しい所です。

質問者様が作りたいというデータフレームがどのような構造で、どのようなエクセルファイルが入力として想定されて、最終的にどのような処理が行いたいのかを今ひとつ理解できていないため、はっきりとしたアドバイスはできませんが、たとえば単にシート名と内部のデータを紐付けたいだけであれば、

sheetname_dataframe_dict = {}
dataframe = pd.read_excel(.....)
sheet_name = "time"
sheetname_dataframe_dict[sheet_name] = dataframe

のような形で登録しておいて、処理が必要な段階で

dataframe_to_process = sheetname_dataframe_dict[sheet_name]

などと個別に呼び出すなどの手法で実現された方が、後々の処理も楽になるのではないでしょうか。

なにかの参考になれば幸いです。

1Like

Comments

  1. @wellwell3176

    Questioner

    @kensussu 様

    試させていただきました。バッチリです。ただ、このやり方は推奨されていないのですね・・・教えていただいた個別呼び出しの方法も少し勉強した上で、実装方法を考えるようにします。

    どうもありがとうございました

Your answer might help someone💌