Python Forum

Full Version: Nested dictionary acting strange
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm trying to collate data from a little survey. The data is in a .csv, 14 questions, each question 7 possible answers.

I make a dictionary:

data_dict = {'Q' + str(i):0 for i in range(1, 15)}
I make a row dictionary:

data_row = {'A' + str(i) + '_total':0 for i in range(1, 8)}
I put the data_row in the question dictionary

for key in data_dict.keys():
    data_dict[key] = data_row
Then this gives output like below:

for item in data_dict.items():
    print(item)
Quote:('Q1', {'A1_total': 0, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q2', {'A1_total': 0, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q3', {'A1_total': 0, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})

I extract the data from the .csv file and get sets of answers like below, each answer represents the choice for each question from Q1 to Q14

Quote:>>> answers_d
['A', 'F', 'A', 'E', 'C', 'D', 'C', 'C', 'B', 'E', 'D', 'E', 'E', 'E']

Now I want to put that in my data_dict. I make a list of tuples (key, answer)

def getTuples(answer_d):
    tups = []
    count = 0
    for key in data_dict.keys():
        mytup = (key, answers_d[count])
        print(mytup)
        tups.append(mytup)
        count +=1
    return tups
tups = getTuples(answers_d)
So tups[0] looks like:

Quote:>>> tup = tups[0]
>>> tup
('Q1', 'A')

Now I want to increment a value in data_dict, according to which answer was chosen:

def getAnswer(key, answer):
    letters = 'ABCDEFG'    
    for l in range(len(letters)):
        if answer == letters[l]:            
            print('key is', key)            
            print('answer is', answer)
            print('found a match', answer, letters[l])
            store_key = 'A' + str(l+1) + '_total'
            print('store_key is', store_key)
            data_dict[key][store_key] = data_dict[key][store_key] + 1
            print('value now is', data_dict[key][store_key])
            return
Quote:>>> key
'Q1'
>>> answer
'A'
>>> getAnswer(key, answer)
key is Q1
answer is A
found a match A A
store_key is A1_total
value now is 1
>>>

BUT, when I look at data_dict now, ALL the values for store_key is A1_total have been incremented, not just Q1

This is not what I expected. The key is definitely Q1, the store_key is A1_total so I expected only data_dict['Q1']['A1_total'] to increment.

Why are all the data_dict['QX']['A1_total'] being incremented?? What am I doing wrong?

Quote:>>> for item in data_dict.items():
print(item)


('Q1', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q2', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q3', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q4', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q5', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q6', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q7', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q8', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q9', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q10', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q11', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q12', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q13', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
('Q14', {'A1_total': 1, 'A2_total': 0, 'A3_total': 0, 'A4_total': 0, 'A5_total': 0, 'A6_total': 0, 'A7_total': 0})
You only made 1 row dictionary and put it in all the questions. The assignment doesn't make a copy of it as it existed at the time, it just links the object. So when you change that object, it changes everywhere.

You need to make 7 independent row dictionaries so each question has a different one. Since there are no object in the dictionary, you can just make a shallow copy.

Instead of
for key in data_dict.keys():
    data_dict[key] = data_row
Maybe something like

for key in data_dict.keys():
    data_dict[key] = data_row.copy()
Thank you very much, that has been puzzling me since yesterday!!

Worked great, first time!