AlbertoCottica
AlbertoCottica

Reputation: 45

Python: declaring dictionaries with keys taken from iterators

I am a Python newbie and am struggling with reorganising data contained in nested dictionaries. The original data are like this:

['period_1': {'metric_1':{'person_1': 0, 'person_2': 1}, 
{'metric_2': {'person_1': 2, 'person_2': 3}}, 'period_2' :{ ...}

What I want to get to is panel data, with people as the main key, followed by periods, followed by metrics. Like this:

{'person_1': {'period_1': {'metric_1': 0, 'metric_2': 2}, 'period_2':
{'metric_1': 4, 'metric_2': 6}, 'period_2'{ ... }}, 'person_2': { ...}

What I tried so far (the dictionary allUsers is going to be the place where I store my reorganised data. It already has persons' IDs as keys, and empty dicts as values):

allUsers = {'pippo':{}, 'pluto':{}}

for t in range (len (periods)):
for user in allUsers:
    allUsers[user][t] = {}
period = periods[t]
for metric in period:
    for person in period[metric]:
        allUsers[person][t] = {metric: period[metric][person]}

For some reason, this does not work. It only stores one of the two metrics.

>>> allUsers
{'pippo': {0: {'metric1': 1}, 1: {'metric1': 1}},
'pluto': {0: {'metric1': 2}, 1: {'metric1': 1}}}

Thank you in advance for any help.

Upvotes: 1

Views: 91

Answers (2)

Fax
Fax

Reputation: 388

You're iterating over periods, metrics and persons, so the composite key [person][period] is not going to be unique for each iteration step. When you assign to that key you overwrite whatever was there previously, i.e. the previous metric dictionary.

Upvotes: 0

Anand S Kumar
Anand S Kumar

Reputation: 90899

The issue is that for every new period/metric you find for a person, you are creating a new dictionary and adding to allUsers[person][t] in the line -

allUsers[person][t] = {metric: period[metric][person]}

Hence it only comes once. You actually want to add a new key/value if t already exists in allUsers . Example -

for metric in period:
    for person in period[metric]:
        allUsers[person][t][metric] = period[metric][person]

But assuming periods is a dictionary , you can simplify this using dict.setdefault. Example -

result = {}
for period, value in periods.items():
    for metric, v in value.items():
        for person,val in v.items():
            result.setdefault(person,{}).setdefault(period,{}).set(metric,val)

Upvotes: 1

Related Questions