Reputation: 2186
I have a list of dictionnaries that all have the same keys.
in_list = [{'index':1, 'value':2.}, {'index':1, 'value':3.}, {'index':2, 'value':4.}]
I'd like to create a new dictionnary with the average on 'value'
for each 'index'
.
out_dict = {1:2.5, 2:4.}
What would be the most pythonic way to do this ?
The following code does what I want, but I feel like it is clumsy
tmp = {x:[] for x in range(1,3)}
for el in in_list:
tmp[el['index']].append(el['value'])
for key, val in tmp.iteritems():
out_dict[key] = sum(val)/len(val)
Upvotes: 4
Views: 663
Reputation: 55469
Your code is fine, but you can make it a little more compact. As Transhuman's answer shows you can avoid initialising tmp
by making it a defaultdict
of lists. Another way to do that is to use the dict.setdefault
method. And then use a dict comprehension to calculate the averages.
in_list = [
{'index':1, 'value':2.},
{'index':1, 'value':3.},
{'index':2, 'value':4.}
]
out_dict = {}
for d in in_list:
out_dict.setdefault(d['index'], []).append(d['value'])
out_dict = {k: sum(v) / len(v) for k, v in out_dict.items()}
print(out_dict)
output
{1: 2.5, 2: 4.0}
Upvotes: 2
Reputation: 71560
To do it without any packages to install (long one-liner :-) ):
import itertools,statistics
a = dict(zip(sorted(set([i['index'] for i in lod])),[statistics.mean(int(item['value']) for item in group) for key, group in itertools.groupby(lod, key=lambda x: x['index'])]))
Now:
print(a)
Returns:
{1: 2.5, 2: 4}
If python 2:
import itertools
a = dict(zip(sorted(set([i['index'] for i in lod]),key=[i['index'] for i in lod].index),[sum(int(item['value']) for item in group)/len(int(item['value']) for item in group) for key, group in itertools.groupby(lod, key=lambda x: x['index'])]))
Explanation:
get the ordered list of unique elements using set
use itertools.groupby
for grouping then iterate by key
a group
, the get average using statistics
or sum
and len
the above two notes are all in a zip
(dict(zip(...))
)
Or to make the code little cleaner:
Python 3:
import itertools,statistics
unique_elements=sorted(set([i['index'] for i in lod]))
groups=statistics.mean(int(item['value']) for item in group) for key, group in itertools.groupby(lod, key=lambda x: x['index'])]
a = dict(zip(unique_elements,groups))
Python 2:
import itertools
unique=sorted(set([i['index'] for i in lod])
groups=[sum(int(item['value']) for item in group)/len(int(item['value']) for item in group) for key, group in itertools.groupby(lod, key=lambda x: x['index'])]
a = dict(unique,groups))
Upvotes: 2
Reputation: 3547
One way you can do is using collections.defaultdict
in_list = [{'index':1, 'value':2.}, {'index':1, 'value':3.}, {'index':2, 'value':4.}]
from collections import defaultdict
d_dict = defaultdict(list)
for k,v in [d.values() for d in in_list]:
d_dict[k].append(v)
{k:sum(v)/len(v) for k,v in d_dict.items()}
#{1: 2.5, 2: 4.0}
Upvotes: 1
Reputation: 78650
I don't think your code is clumsy, but you could check out pandas
.
>>> import pandas as pd
>>> in_list = [{'index':1, 'value':2.}, {'index':1, 'value':3.}, {'index':2, 'value':4.}]
>>>
>>> df = pd.DataFrame(in_list)
>>> df.groupby(by='index').mean()
value
index
1 2.5
2 4.0
You can transform the result to a standard dictionary if you like.
>>> df.groupby(by='index').mean().to_dict()['value']
{1: 2.5, 2: 4.0}
Upvotes: 1