0xOsiris
0xOsiris

Reputation: 277

Python summing up values in a nested dictionary

I have a dictionary P which represents a dictionary within a dictionary within a dictionary. It looks something like this.

P={key1:{keyA:{value1: 1, value2:3}, keyB:{value1:3,value2:4}}, 
key2:{keyA:{value1: 1, value2:3}, keyB:{value1:3,value2:4}}, key3{...:{...:}}}

What I am trying to do is to write each value of value1,value 2 in terms of their percentages of the totalPopulation from whichever is there base key.

For example key1 should look like

key1:{keyA:{value1: 1/(1+3+3+4), value2:3/(1+3+3+4)}, keyB:
{value1:3/(1+3+3+4),value2:4/(1+3+3+4)}

What I am not sure about is how to iterate over this dictionary and only collect the innermost values of a certain key so I can then sum up all the values and divide each value by that sum.

Upvotes: 1

Views: 478

Answers (2)

Ashish Ranjan
Ashish Ranjan

Reputation: 5543

This can be done in single line using dict comprehension and map like this:

#from __future__ import division # use for Python 2.x
p = {"key1":{"keyA":{"value1": 1, "value2":3}, "keyB":{"value1":3,"value2":4}}}

p = {kOuter:{kInner:{kVal: vVal/sum(map(lambda x: sum(x.values()), vOuter.values())) for kVal, vVal in vInner.iteritems()} for kInner, vInner in vOuter.iteritems()} for kOuter, vOuter in p.iteritems()}

A more readable version of above :

p = {
        kOuter:{
            kInner:{
                kVal: vVal/sum(map(lambda x: sum(x.values()), vOuter.values())) for kVal, vVal in vInner.iteritems()
            } 
            for kInner, vInner in vOuter.iteritems()
        } 
        for kOuter, vOuter in p.iteritems()
    }

OUTPUT

>>> p
>>> 
{'key1': {'keyB': {'value2': 0.36363636363636365, 'value1': 0.2727272727272727}, 'keyA': {'value2': 0.2727272727272727, 'value1': 0.09090909090909091}}}

The only problem with this is that the sum is calculated repeatedly, you can fix that by calculating the sum for each of your key1, key2... before this dict comprehension and use the stored values instead, like this :

keyTotals = {kOuter:sum(map(lambda x: sum(x.values()), vOuter.values())) for kOuter, vOuter in p.iteritems()}

and then you can simply access the sums calculated above by keys, like this:

p = {kOuter:{kInner:{kVal: vVal/keyTotals[kOuter] for kVal, vVal in vInner.iteritems()} for kInner, vInner in vOuter.iteritems()} for kOuter, vOuter in p.iteritems()}

Upvotes: 1

maksel
maksel

Reputation: 120

test = {"key1":{"keyA":{"value1": 1, "value2":3}, "keyB":{"value1":3,"value2":4}}}

for a in test:
        s = 0
        for b in test[a]:
            for c in test[a][b]:
                s += test[a][b][c]
        print(s)
        for b in test[a]:
            for c in test[a][b]:
                test[a][b][c] = test[a][b][c] / s

This should do what you want. I've only included "key1" in this example.

Upvotes: 1

Related Questions