HAO CHEN
HAO CHEN

Reputation: 1319

Average value in multiple dictionaries based on key in Python?

I have three dictionaries (or more):

A = {'a':1,'b':2,'c':3,'d':4,'e':5}
B = {'b':1,'c':2,'d':3,'e':4,'f':5}
C = {'c':1,'d':2,'e':3,'f':4,'g':5}

How can I get a dictionary of the average values of every key in the three dictionaries?

For example, given the above dictionaries, the output would be:

{'a':1/1, 'b':(2+1)/2, 'c':(3+2+1)/3, 'd':(4+3+2)/3, 'e':(5+4+3)/3, 'f':(5+4)/2, 'g':5/1}

Upvotes: 11

Views: 8391

Answers (5)

Yann Dubois
Yann Dubois

Reputation: 1345

Here's a very general way to do so (i.e. you can easily change to any aggregation function).:

def aggregate_dicts(dicts, operation=lambda x: sum(x) / len(x)):
    """
    Aggregate a sequence of dictionaries to a single dictionary using `operation`. `Operation` should
    reduce a list of all values with the same key. Keyrs that are not found in one dictionary will
    be mapped to `None`, `operation` can then chose how to deal with those.
    """
    all_keys = set().union(*[el.keys() for el in dicts])
    return {k: operation([dic.get(k, None) for dic in dicts]) for k in all_keys}

example:

dicts_diff_keys = [{'x': 0, 'y': 1}, {'x': 1, 'y': 2}, {'x': 2, 'y': 3, 'c': 4}]

def mean_no_none(l):
    l_no_none = [el for el in l if el is not None]
    return sum(l_no_none) / len(l_no_none)

aggregate_dicts(dicts_diff_keys, operation= mean_no_none)
#{'x': 1.0, 'c': 4.0, 'y': 2.0}

Upvotes: 0

Maxim Imakaev
Maxim Imakaev

Reputation: 1545

You can use Pandas, like this:

import pandas as pd
df = pd.DataFrame([A,B,C])
answer = dict(df.mean())
print(answer)

Upvotes: 17

Xiaoqi Chu
Xiaoqi Chu

Reputation: 1557

I use Counter to solve this problem. Please try the following code :)

from collections import Counter

A = {'a':1,'b':2,'c':3,'d':4,'e':5}
B = {'b':1,'c':2,'d':3,'e':4,'f':5}
C = {'c':1,'d':2,'e':3,'f':4,'g':5}

sums = Counter()
counters = Counter()
for itemset in [A, B, C]:
    sums.update(itemset)
    counters.update(itemset.keys())

ret = {x: float(sums[x])/counters[x] for x in sums.keys()}

print ret

Upvotes: 8

Andrew
Andrew

Reputation: 734

If you are working in python 2.7 or 3.5 you can use the following:

keys = set(A.keys()+B.keys()+C.keys())

D = {key:(A.get(key,0)+B.get(key,0)+C.get(key,0))/float((key in A)+(key in B)+(key in C)) for key in keys}

which outputs

 D
{'a': 1.0, 'c': 2.0, 'b': 1.5, 'e': 4.0, 'd': 3.0, 'g': 5.0, 'f': 4.5}

if you don't want to use any packages. This doesn't work in python 2.6 and below though.

Upvotes: 0

Marco Bonelli
Marco Bonelli

Reputation: 69346

The easiest way would be to use collections.Counter as explained here, like this:

from collections import Counter

sums = dict(Counter(A) + Counter(B) + Counter(C))
# Which is {'a': 1, 'c': 6, 'b': 3, 'e': 12, 'd': 9, 'g': 5, 'f': 9}

means = {k: sums[k] / float((k in A) + (k in B) + (k in C)) for k in sums}

The result would be:

>>> means
{'a': 1.0, 'b': 1.5, 'c': 2.0, 'd': 3.0, 'e': 4.0, 'f': 4.5, 'g': 5.0}

Upvotes: 3

Related Questions