Reputation: 299
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
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
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
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
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
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
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
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