saul
saul

Reputation: 299

sum list of dictionary values

I have a list of dictionary in this form :

[
{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8}, 

{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},

{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},
]

and I want to sum the values in this by key for each element in the list like that :

    {
     'signal_8': 3,
     'signal_1': 21,
     'signal_10': 15,
     'signal_5': 6,
     'signal_2': 15,
     'signal_6': 9,
     'signal_4': 27,
     'signal_3': 18,
     'signal_9': 12,
     'signal_7': 24
    }

what I have tried is the following :

    result = {}
    sm = 0
    for elm in original_list:
        for k,v in elm.items():
            sm += v
            result[k] = sm
    print(result)

but it still doesn't work.

Upvotes: 7

Views: 14276

Answers (7)

U13-Forward
U13-Forward

Reputation: 71610

Try this:

original_list = [
{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8}, 

{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},

{'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},
]
print({k:sum([x[k] for x in original_list if k in x]) for i in original_list for k,v in i.items()})

Output:

{'signal_8': 3, 'signal_1': 21, 'signal_10': 15, 'signal_5': 6, 'signal_2': 15, 'signal_6': 9, 'signal_4': 27, 'signal_3': 18, 'signal_9': 12, 'signal_7': 24}

Note that if there are missing signals, it will just consider it as zero

Upvotes: 0

timgeb
timgeb

Reputation: 78780

Similar to daveruinseverything's answer, I'd solve this with a Counter, but make use of its update method.

Let signals be your list of dicts.

>>> from collections import Counter
>>> c = Counter()
>>> for d in signals:
...     c.update(d)
... 
>>> c
Counter({'signal_4': 27, 'signal_7': 24, 'signal_1': 21, 'signal_3': 18, 'signal_10': 15, 'signal_2': 15, 'signal_9': 12, 'signal_6': 9, 'signal_5': 6, 'signal_8': 3})

For Op's sake, can you briefly describe what's happening here?

A Counter works similar to a dict, but its update method adds values to the values of pre-existing keys instead of overriding them.

Upvotes: 13

daveruinseverything
daveruinseverything

Reputation: 5187

What you want is the Counter collection type. The Python docs on collections describe it best, but essentially a Counter is a special kind of dictionary where all the values are integers. You can pass any key, including nonexistent ones, and add to them. For example:

from collections import Counter

original_list = [
    {'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8}, 
    {'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},
    {'signal_8': 1, 'signal_1': 7, 'signal_10': 5, 'signal_5': 2, 'signal_2': 5, 'signal_6': 3, 'signal_4': 9, 'signal_3': 6, 'signal_9': 4, 'signal_7': 8},
]

result = Counter()

for elem in original_list:
    for key, value in elem.items():
        result[key] += value

print(result)

Edit: @timgeb provides a variation on this answer which makes native use of the update() method on Counter objects. I would recommend that as the best answer here

Upvotes: 2

RoadRunner
RoadRunner

Reputation: 26335

Your current code uses one accumulating sum for all the signals, when instead you need a seperate the sum for each signal.

If you want your original code to work, you need to first check if the key exists in result, and initialise it 0 beforehand if it isn't. Then accumulate the sum for the respective key.

Code:

result = {}
for elm in original_list:
    for k, v in elm.items():

        # Initialise it if it doesn't exist
        if k not in result:
            result[k] = 0

        # accumulate sum seperately 
        result[k] += v

print(result)

Output:

{'signal_9': 12, 'signal_8': 3, 'signal_1': 21, 'signal_3': 18, 'signal_2': 15, 'signal_5': 6, 'signal_4': 27, 'signal_7': 24, 'signal_6': 9, 'signal_10': 15}

Note: As others have shown, to avoid initialising yourself, you can use collections.defaultdict() or collections.Counter() instead.

Upvotes: 1

Naseer Mohammad
Naseer Mohammad

Reputation: 431

Can you try below code

basedict=siglist[0]
for k in basedict.keys():
    result=[currdict[k] for currdict in siglist]
    endval=sum(result)
    print("Key %s and sum of values %d"%(k,endval))

Output

Key signal_9 and sum of values 12
Key signal_2 and sum of values 15
Key signal_8 and sum of values 3
Key signal_5 and sum of values 6
Key signal_7 and sum of values 24
Key signal_10 and sum of values 15
Key signal_1 and sum of values 21
Key signal_6 and sum of values 9
Key signal_4 and sum of values 27
Key signal_3 and sum of values 18

Note :- As we are sure that all keys in all dictionaries are same this solution works well. If you have a dictionary with non matching elements then it would result in KeyError . So be aware of that limitation

Upvotes: 0

fuglede
fuglede

Reputation: 18221

With itertools.groupby, you could do something like

merged_list = sorted(p for l in original_list for p in l.items())
groups = groupby(merged_list, key=lambda p: p[0])
result = {signal: sum(pair[1] for pair in pairs) for signal, pairs in groups}

If you can assume that each dictionary contains the exact same keys, the above can be simplified to

{k: sum(d[k] for d in original_list) for k in original_list[0]}

Note also that the data analysis library pandas makes operations such as these trivial:

In [70]: import pandas as pd

In [72]: pd.DataFrame(original_list).sum()
Out[72]:
signal_1     21
signal_10    15
signal_2     15
signal_3     18
signal_4     27
signal_5      6
signal_6      9
signal_7     24
signal_8      3
signal_9     12
dtype: int64

Upvotes: 2

iulian
iulian

Reputation: 5822

The problem with your code is that you are summing sm and v no matter the key. Below you can find a reformatted version of your code that works. It simply adds the values from each element from the list to the result object:

from collections import defaultdict

result = defaultdict(int)

for elm in original_list:
    for k, v in elm.items():
        result[k] += v
print(result)

Or, with a one liner you can have:

result = {key: sum(e[key] for e in original_list) for key in original_list[0].keys()}

Upvotes: 3

Related Questions