Pythonic way of counting max elements by index in a dictionary with list values

Question:

I want to compare the lists inside a dictionary (as values) by each index, and save in another dictionary how many times each "key" had the highest value.

Let’s put an example, I have this dictionary:

my_dict = {'a': [1, 2, 5], 'b': [2, 1, 4], 'c': [1, 0, 3]}

I want to end up with a dictionary like this:

count_dict = {'a': 2, 'b': 1, 'c': 0}

Because:

  • at index 0 of the lists we have:
    1 from ‘a’ ; 2 from ‘b’ ; and 1 from ‘c’.

    So ‘b’ has the highest value for this index and adds one to the count.

  • at index 1 of the lists we have:
    2 from ‘a’ ; 1 from ‘b’ ; and 0 from ‘c’.

    So ‘a’ has the highest value for this index and adds one to the count.

  • at index 2 of the lists we have:
    5 from ‘a’ ; 4 from ‘b’ ; and 3 from ‘c’.

    So ‘a’ has the highest value for this index and adds one to the count.


I’ve tried with Counter and max(my_dict, key=my_dict.get). But what would be the most pythonic way instead of doing this:

for i in range(len(my_dict['a'])):
    max_value = max(my_dict[key][i] for key in my_dict)
    for key in my_dict:
        if my_dict[key][i] == max_value:
            max_count[key] += 1

print(max_count)
Asked By: Tonino Fernandez

||

Answers:

An alternative approach using zip() together with enumerate and lambda.

dict_result = {key: 0 for key in my_dict}

for idx, values in enumerate(zip(*my_dict.values())):
    max_key = max(my_dict, key=lambda k: my_dict[k][idx])
    dict_result[max_key] += 1
    
print(dict_result)

{'a': 2, 'b': 1, 'c': 0}
Answered By: Jamiu S.

You can zip them:

res = {k:0 for k in my_dict}
keys = [*my_dict] # note that order in dictionaries is only guaranteed in python 3.7+
for l in zip(*my_dict.values()):
   res[keys[l.index(max(l))]] += 1
Answered By: Axeltherabbit

You can zip the values after manipulating them to contain their respective key:

zip(*([(k, v) for v in l] for k, l in my_dict.items()))
# gives: [(('a', 1), ('b', 2), ('c', 1)), (('a', 2), ('b', 1), ('c', 0)), (('a', 5), ('b', 4), ('c', 3))]

and now for each item, find the max according to the value, and increment the count of the matching key:

from collections import Counter

my_dict = {'a': [1, 2, 5], 'b': [2, 1, 4], 'c': [1, 0, 3]}

c = Counter()
for item in zip(*([(k, v) for v in l] for k, l in my_dict.items())):
    c[max(item, key=lambda x: x[1])[0]] += 1

print(c)

Will print {'a': 2, 'b': 1} since c was never added. But the beauty with Counters is that even if you do c['c'] you will still get 0.


This doesn’t rely on the keys’ order or index and so will work for any Python version.

Answered By: Tomerikoo
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.