【Python基礎】ネスト(複数の階層)された辞書の作成方法

  • URLをコピーしました!

辞書

前回、Pythonの複数のfor文からbreakで全てのfor文から抜ける方法を紹介しました。

今回はネスト(複数の階層)された辞書の作成方法を紹介します。

事の発端はこんな感じで複数の階層をもつ(つまりネストされた)辞書を作成しようとした時にエラーとなってしまったことです。

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i, val1 in enumerate(val1_list):
    for j, val2 in enumerate(val2_list):
        result_dict[i][j] = val1*val2

print(result_dict)

実行結果
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[1], line 7
      5 for i, val1 in enumerate(val1_list):
      6     for j, val2 in enumerate(val2_list):
----> 7         result_dict[i][j] = val1*val2
      9 print(result_dict)

KeyError: 0

どうやらこのように複数の階層の下へ階層を作りつつ、一気に要素を格納することはできないようです。

ではどうしたらいいのかと考えて、やってみた結果を紹介します。

先に階層構造を作ってしまう方法

まずはとりあえずfor文を一回まわして階層だけ作り、2回目に要素を入れていく方法です。

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i in range(len(val1_list)):
    result_dict[i] = {}
    for j in range(len(val2_list)):
        result_dict[i][j] = {}

for i, val1 in enumerate(val1_list):
    for j, val2 in enumerate(val2_list):
        result_dict[i][j] = val1*val2

print(result_dict)

実行結果
{0: {0: 600, 1: 700, 2: 800, 3: 900, 4: 1000}, 
1: {0: 1200, 1: 1400, 2: 1600, 3: 1800, 4: 2000}, 
2: {0: 1800, 1: 2100, 2: 2400, 3: 2700, 4: 3000}, 
3: {0: 2400, 1: 2800, 2: 3200, 3: 3600, 4: 4000}, 
4: {0: 3000, 1: 3500, 2: 4000, 3: 4500, 4: 5000}}

コードが冗長になってしまいますが、役割がはっきりしていて分かりやすいかもしれません。

階層構造を作りつつ、要素を入れていく方法

次は一段ずつ階層構造を作りつつ、要素を入れていく方法です。

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i, val1 in enumerate(val1_list):
    result_dict[i] = {}
    for j, val2 in enumerate(val2_list):
        result_dict[i][j] = val1*val2

print(result_dict)

実行結果
{0: {0: 600, 1: 700, 2: 800, 3: 900, 4: 1000}, 
1: {0: 1200, 1: 1400, 2: 1600, 3: 1800, 4: 2000}, 
2: {0: 1800, 1: 2100, 2: 2400, 3: 2700, 4: 3000}, 
3: {0: 2400, 1: 2800, 2: 3200, 3: 3600, 4: 4000}, 
4: {0: 3000, 1: 3500, 2: 4000, 3: 4500, 4: 5000}}

作り方としてはこれがストレートな感じがします。

先に下の階層を作り、上の階層に格納する方法

最後は先に下の階層に要素を入れて完成させて、その後、上の階層に格納する方法です。

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i, val1 in enumerate(val1_list):
    result_dict_temp = {}
    for j, val2 in enumerate(val2_list):
        result_dict_temp[j] = val1*val2
    result_dict[i] = result_dict_temp

print(result_dict)

実行結果
{0: {0: 600, 1: 700, 2: 800, 3: 900, 4: 1000}, 
1: {0: 1200, 1: 1400, 2: 1600, 3: 1800, 4: 2000}, 
2: {0: 1800, 1: 2100, 2: 2400, 3: 2700, 4: 3000}, 
3: {0: 2400, 1: 2800, 2: 3200, 3: 3600, 4: 4000}, 
4: {0: 3000, 1: 3500, 2: 4000, 3: 4500, 4: 5000}}

要素を格納していく順番にコードが書けるので理解がしやすいかもしれません。

処理速度の比較

とりあえずは書きやすいものを使えばいいと思いますが、処理速度に違いがあるのかをマジックコマンド「%%timeit」を使って確認してみました。

・先に階層構造を作ってしまう方法

%%timeit

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i in range(len(val1_list)):
    result_dict[i] = {}
    for j in range(len(val2_list)):
        result_dict[i][j] = {}

for i, val1 in enumerate(val1_list):
    for j, val2 in enumerate(val2_list):
        result_dict[i][j] = val1*val2

実行結果
10.1 μs ± 289 ns per loop (mean ± std. dev. of 7 runs, 
100,000 loops each)

・階層構造を作りつつ、要素を入れていく方法

%%timeit

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i, val1 in enumerate(val1_list):
    result_dict[i] = {}
    for j, val2 in enumerate(val2_list):
        result_dict[i][j] = val1*val2

実行結果
5.43 μs ± 88.1 ns per loop (mean ± std. dev. of 7 runs, 
100,000 loops each)

・先に下の階層を作り、上の階層に格納する方法

%%timeit

val1_list = [10, 20, 30, 40, 50]
val2_list = [60, 70, 80, 90, 100]

result_dict = {}
for i, val1 in enumerate(val1_list):
    result_dict_temp = {}
    for j, val2 in enumerate(val2_list):
        result_dict_temp[j] = val1*val2
    result_dict[i] = result_dict_temp

実行結果
4.86 μs ± 49.3 ns per loop (mean ± std. dev. of 7 runs, 
100,000 loops each)

3回ずつくらい試してみましたが、大体同じ結果になりました。

「先に階層構造を作ってしまう方法」はやはり同じfor文を2回回すことになることから、倍の時間がかかってしまいます。

「階層構造を作りつつ、要素を入れていく方法」と「先に下の階層を作り、上の階層に格納する方法」は大体同じ処理時間でしたが、若干「先に下の階層を作り、上の階層に格納する方法」の方が速い感じでした。

次回はPandasの「FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. 」の警告への対処法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする