1

I'm trying to create a loop to populate a dictionary within a dictionary from a Series:
The expected result is:

{1: {'KEY Mult. by 10': 10, 'KEY Add by 10': 11},
 2: {'KEY Mult. by 10': 20, 'KEY Add by 10': 12},
 3: {'KEY Mult. by 10': 30, 'KEY Add by 10': 13},
 4: {'KEY Mult. by 10': 40, 'KEY Add by 10': 14},
 5: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15}}

what I'm doing is:

series_1 = pd.Series([1,2,3,4,5])

first_dict = dict()                         # creating first level of Dict 
second_dict = dict({'KEY Mult. by 10': 0,   # creating second level of Dict
                   'KEY Add by 10': 0})

for i in series_1:
       
    first_dict[i] = second_dict
 
    first_dict[i]['KEY Mult. by 10'] = i *10
    first_dict[i]['KEY Add by 10'] = i + 10

The result from the above ends up being:

{1: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15},
 2: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15},
 3: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15},
 4: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15},
 5: {'KEY Mult. by 10': 50, 'KEY Add by 10': 15}}

Then, when I try to change value for one of the keys, it changes for all of them:

first_dict[3]['KEY Mult. by 10'] = 20

print(first_dict)

{1: {'KEY Mult. by 10': 20, 'KEY Add by 10': 15},
 2: {'KEY Mult. by 10': 20, 'KEY Add by 10': 15},
 3: {'KEY Mult. by 10': 20, 'KEY Add by 10': 15},
 4: {'KEY Mult. by 10': 20, 'KEY Add by 10': 15},
 5: {'KEY Mult. by 10': 20, 'KEY Add by 10': 15}}

Can any one help me please?

3 Answers3

3

Some of the comments describe the solution but I'll elaborate some.

The dictionary is the same block of memory in each of the outer indices. To see this after you run:

for i in series_1:
    first_dict[i] = second_dict

look at the id() of two of the inner dictionaries, these are the memory locations:

id(first_dict[1]) # 4511987904
id(first_dict[2])

With the way the code is currently written any write to any of the dictionaries will overwrite all of them.
On your machine you will have a (a single one) different value for the ids but it is the same idea-they will be all the same memory location.

To fix this you can call the constructor inside the for loop and it will allocate new memory for each inner dictionary.

for i in series_1:
    first_dict[i] = dict({'KEY Mult. by 10': 0,'KEY Add by 10': 0})
    first_dict[i]['KEY Mult. by 10'] = i * 10
    first_dict[i]['KEY Add by 10'] = i + 10

then you will see different id() return values for each inner dictionary and you can confirm they are different memory locations with id():

>>> id(first_dict[3])
4511988352
>>> id(first_dict[1])
4511988160

again, on your machine these will be different id() values but the idea is the same, you are making space for each inner dictionary separately.

Lucas Roberts
  • 1,252
  • 14
  • 17
  • Thank you so much for the detailed explanation!... looking at **omercotkd's** comment, I believe the below change would be the best.. right? first_dict[i] = dict({'KEY Mult. by 10': 0,'KEY Add by 10': 0}) first_dict[i] = dict() because then the code will create the 2 keys inside each of the dictionaries :D thank you again!! – Jefferson Robinski Apr 03 '22 at 11:10
  • @JeffersonRobinski YMMV. The distinction of best here is most likely your preference. I'm not sure how large the data are or how much updating you'd need to perform in your actual implementation. If you have many candidate multiply or add values then doing all of them-if possible-and then doing a single `dict.update()` might make more sense. Outside of the scenario I just mentioned, I'd probably use the constructor example I wrote above. – Lucas Roberts Apr 03 '22 at 17:27
1

Change first_dict[i] = second_dict to: first_dict[i] = dict() and it will work as expacted, by doing so you can also remove the creation of the "second level of Dict"

omercotkd
  • 493
  • 1
  • 6
  • 13
1

The problem is, that u use the same dictionary multiple times, you have to use a copy oh the second_dict

import pandas as pd

series_1 = pd.Series([1, 2, 3, 4, 5])

first_dict = dict()  # creating first level of Dict
second_dict = dict({'KEY Mult. by 10': 0,  # creating second level of Dict
                    'KEY Add by 10': 0})

for i in series_1:
    first_dict[i] = second_dict.copy()

    first_dict[i]['KEY Mult. by 10'] = i * 10
    first_dict[i]['KEY Add by 10'] = i + 10
D-E-N
  • 1,242
  • 7
  • 14