Edamame
Edamame

Reputation: 25376

Find top counted element in a dictionary of a dictionary

I have a dictionary of dictionary myDict:

myDict = { 'cow': {'A':2, 'B':5, 'C':3},
           'cat': {'A':7, 'B':1, 'C':6},
           'dog': {'A':1, 'B':4, 'C':3},
           'bird': {'A':5, 'B':7, 'C':9}
         }

I want to find the top count element for each animal in this case, i.e. the output should be:

myNewTable = {'cow':'B', 'cat':'A', 'dog':'B', 'bird':'C'}

I tried to achieve this using the following code:

 myNewTable = max(x.items(), key=operator.itemgetter(1))[0] for x in myDict

but got the following error:

File "<ipython-input-11-3bcb909a6476>", line 28
    myNewTable = max(x.items(), key=operator.itemgetter(1))[0] for x in myDict
                                                                ^
SyntaxError: invalid syntax

What did I do wrong here ? And how could I fix this?

Upvotes: 3

Views: 54

Answers (3)

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48090

Another alternative using collections.Counter with its .most_common(...) method:

>>> from collections import Counter

>>> {k: Counter(v).most_common(1)[0][0] for k, v in myDict.items()}
{'cat': 'A', 'bird': 'C', 'cow': 'B', 'dog': 'B'}

This will be useful in general if you want to select more than one highest count elements from the nested dict. For example, below is the sample to select list of two most common keys in dict:

>>> {k: [x[0] for x in Counter(v).most_common(2)] for k, v in myDict.items()}
{'dog': ['B', 'C'], 'bird': ['C', 'B'], 'cat': ['A', 'C'], 'cow': ['B', 'C']}

From the Counter.most_common([n]) document:

Return a list of the n most common elements and their counts from the most common to the least. If n is omitted or None, most_common() returns all elements in the counter. Elements with equal counts are ordered arbitrarily:

Upvotes: 1

AChampion
AChampion

Reputation: 30268

You are using comprehension syntax but haven't wrapped it in a specific type (e.g. list => [], set => {}, dict => {:}). So fixing your code it would look like:

In []:
[max(myDict[x].items(), key=operator.itemgetter(1))[0] for x in myDict]

Out[]:
['B', 'A', 'B', 'C']

But you wanted it as a dict, so perhaps you meant:

In []:
{x: max(myDict[x].items(), key=operator.itemgetter(1))[0] for x in myDict}

Out[]:
{'bird': 'C', 'cat': 'A', 'cow': 'B', 'dog': 'B'}

But can be specified more succinctly (as per @coldspeed's answer):

{x: max(myDict[x], key=myDict[x].get) for x in myDict}

Upvotes: 3

cs95
cs95

Reputation: 402844

Well, your syntax is wrong, but you have the right idea. A nice and succinct solution using max and dict.get can be built on by iterating over myDict:

>>> {k : max(v, key=v.get) for k, v in myDict.items()}
{'bird': 'C', 'cat': 'A', 'cow': 'B', 'dog': 'B'}

Upvotes: 5

Related Questions