306

Suppose I have a list of items, like:

['apple', 'red', 'apple', 'red', 'red', 'pear']

I want a dictionary that counts how many times each item appears in the list. So for the list above the result should be:

{'apple': 2, 'red': 3, 'pear': 1}

How can I do this simply in Python?


If you are only interested in counting instances of a single element in a list, see How do I count the occurrences of a list item?.

3

10 Answers 10

414

In 2.7 and 3.1, there is the special Counter (dict subclass) for this purpose.

>>> from collections import Counter
>>> Counter(['apple','red','apple','red','red','pear'])
Counter({'red': 3, 'apple': 2, 'pear': 1})
Sign up to request clarification or add additional context in comments.

8 Comments

The official line, or rather standing joke, is that Guido has a time machine ..
@Glenn Maynard Counter is just an implementation of a multiset which is not an uncommon data structure IMO. In fact, C++ has an implementation in the STL called std::multiset (also std::tr1::unordered_multiset) so Guido is not alone in his opinion of its importance.
@awesomo: No, it's not comparable to std::multiset. std::multiset allows storing multiple distinct but comparatively equal values, which is what makes it so useful. (For example, you can compare a list of locations by their temperature, and use a multiset to look up all locations at a specific temperature or temperature range, while getting the fast insertions of a set.) Counter merely counts repetitions; distinct values are lost. That's much less useful--it's nothing more than a wrapped dict. I question calling that a multiset at all.
@GlennMaynard You're right, I overlooked the additional (extremely useful) features of std::multiset.
Counting might be a narrow task, but one that is required very often.
|
360

I like:

counts = dict()
for i in items:
  counts[i] = counts.get(i, 0) + 1

.get allows you to specify a default value if the key does not exist.

9 Comments

For those new to python. This answer is better in terms of time complexity.
This answer works even on a list of floating point numbers, where some of the numbers may be '0'
This answer also does not require any extra imports. +1
I don't understand what does the +1 part does. Could someone explain?
@JonasPalačionis: It increments the counter for that key, before assigning back to the value for that key. i.e. it's a histogram aka frequency-count.
|
78

Simply use list property count\

i = ['apple','red','apple','red','red','pear']
d = {x:i.count(x) for x in i}
print d

output :

{'pear': 1, 'apple': 2, 'red': 3}

3 Comments

You're applying count against the array as many times as there are array items. Your solution is O(n^2) where the better trivial solution is O(n). See comments on riviera's answer versus comments on mmdreg's answer.
Maybe you could do d = {x:i.count(x) for x in set(i)}
@XeniaIoannidou: That does O(n * unique_elements) work; not much better unless you have many repeats. And still bad; building a set() is basically adding elements to a hash table without a count. Almost as much work as just adding them to a Dictionary of counts and incrementing the count if already present, and that's just for making the set. What I described for adding to a Dictionary is already a full solution to the histogram problem, and you're done there without any time spent scanning the original array for each unique element.
67
>>> L = ['apple','red','apple','red','red','pear']
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> for i in L:
...   d[i] += 1
>>> d
defaultdict(<type 'int'>, {'pear': 1, 'apple': 2, 'red': 3})

2 Comments

@NickT It's more cluttered than itertools.Counter - and I'd be surprised if it was faster...
By itertools.Counter I think @Shadow meant collections.Counter
34

I always thought that for a task that trivial, I wouldn't want to import anything. But i may be wrong, depending on collections.Counter being faster or not.

items = "Whats the simpliest way to add the list items to a dictionary "

stats = {}
for i in items:
    if i in stats:
        stats[i] += 1
    else:
        stats[i] = 1

# bonus
for i in sorted(stats, key=stats.get):
    print("%d×'%s'" % (stats[i], i))

I think this may be preferable to using count(), because it will only go over the iterable once, whereas count may search the entire thing on every iteration. I used this method to parse many megabytes of statistical data and it always was reasonably fast.

3 Comments

Your answer deserves more credit for it's simplicity. I was struggling over this for a while, getting bewildered with the silliness of some of the other users suggesting to import new libraries etc.
you could simplify it with a default value like this d[key] = d.get(key, 0) + 1
The simplicity of this answer is so underrated! Sometimes there is no need to import libraries and over-engineer simple tasks.
6
L = ['apple','red','apple','red','red','pear']
d = {}
[d.__setitem__(item,1+d.get(item,0)) for item in L]
print d 

Gives {'pear': 1, 'apple': 2, 'red': 3}

1 Comment

Please don't abuse list comprehensions for side effects like this. The imperative loop is much clearer, and does not create a useless temporary list of Nones.
3

If you use Numpy, the unique function can tell you how many times each value appeared by passing return_counts=True:

>>> data = ['apple', 'red', 'apple', 'red', 'red', 'pear']
>>> np.unique(data, return_counts=True)
(array(['apple', 'pear', 'red'], dtype='<U5'), array([2, 1, 3]))

The counts are in the same order as the distinct elements that were found; thus we can use the usual trick to create the desired dictionary (passing the two elements as separate arguments to zip):

>>> dict(zip(*np.unique(data, return_counts=True)))
{'apple': 2, 'pear': 1, 'red': 3}

If you specifically have a large input Numpy array of small integers, you may get better performance from bincount:

>>> data = np.random.randint(10, size=100)
>>> data
array([1, 0, 0, 3, 3, 4, 2, 4, 4, 0, 4, 8, 7, 4, 4, 8, 7, 0, 0, 2, 4, 2,
       0, 9, 0, 2, 7, 0, 7, 7, 5, 6, 6, 8, 4, 2, 7, 6, 0, 3, 6, 3, 0, 4,
       8, 8, 9, 5, 2, 2, 5, 1, 1, 1, 9, 9, 5, 0, 1, 1, 9, 5, 4, 9, 5, 2,
       7, 3, 9, 0, 1, 4, 9, 1, 1, 5, 4, 7, 5, 0, 3, 5, 1, 9, 4, 8, 8, 9,
       7, 7, 7, 5, 6, 3, 2, 4, 3, 9, 6, 0])
>>> np.bincount(data)
array([14, 10,  9,  8, 14, 10,  6, 11,  7, 11])

The nth value in the output array indicates the number of times that n appeared, so we can create the dictionary if desired using enumerate:

>>> dict(enumerate(np.bincount(data)))
{0: 14, 1: 10, 2: 9, 3: 8, 4: 14, 5: 10, 6: 6, 7: 11, 8: 7, 9: 11}

Comments

1

That is an easy answer m8!

def equalizeArray(arr):
    # Counting the frequency of each element in the array
    freq = {}
    for i in arr:
        if i not in freq:
            freq[i] = 1
        else:
            freq[i] += 1
    # Finding the element with the highest frequency
    max_freq = max(freq.values())
    # Calculating the number of deletions required
    for key,value in freq.items():
        if value == max_freq:
            print(key,"been repeated:",value,"times")

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

First create a list of elements to count

elements = [1, 2, 3, 2, 1, 3, 2, 1, 1, 4, 5, 4, 4]

make an empty dictionary, we also do the same with lists

>>> counts = {}

create a for loop that will count for the occurrences of the "key", for each occurrence we add 1

for element in elements:
   if element in counts:
   counts[element] +=1

check whether we encountered the key before or not if so we add 1, if not we use "else" so the new key is added to the dictionary.

>>> else:
>>> counts[element] = 1

Now print counts using 'items() so we could create sequence of the key-value pairs

for element, count in counts.items():
   print(element, ":", count)

here the items() method shows us the key-value pairs, as if we ask: "for element aka in the element load the previous data into 'count' and update it into a sequence of key-value pairs which is what the item() does

CODE WITH NO COMMENTARY:

    elements = [1, 2, 3, 2, 1, 3, 2, 1, 1, 4, 5, 4, 4]
    counts = {}
    for element in elements:
        if element in counts:
            counts[element] += 1
        else:
            counts[element] = 1
    
    for element, count in counts.items():
        print(element, ":", count)
OUTPUT:
    1:4
    2:3
    3:2
    4:3
    5:1

Comments

-1
mylist = [1,2,1,5,1,1,6,'a','a','b']
result = {}
for i in mylist:
    result[i] = mylist.count(i)
print(result)

2 Comments

No, not a good idea. Runtime complexity is O(n^2) which pretty much defeats the point of using the dictionary in the first place. Same problem as this answer: stackoverflow.com/a/36284223
A code-only answer is not high quality. While this code may be useful, you can improve it by saying why it works, how it works, when it should be used, and what its limitations are. Please edit your answer to include explanation and link to relevant documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.