Respostas:
Se você deseja apenas a contagem de um item, use o count
método:
>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3
Não use isso se quiser contar vários itens. A chamada count
em loop requer uma passagem separada sobre a lista para cada count
chamada, o que pode ser catastrófico para o desempenho. Se você deseja contar todos os itens, ou mesmo apenas vários itens, use Counter
, conforme explicado nas outras respostas.
Use Counter
se você estiver usando Python 2.7 ou 3.x e desejar o número de ocorrências para cada elemento:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
isinstance
. Portanto, se você tiver certeza dos dados com os quais está trabalhando, talvez seja melhor escrever uma função personalizada sem verificação de tipo e instância.
isinstance
chama? Mesmo com milhões de strings, a chamada Counter
envolve apenas uma isinstance
chamada, para verificar se o argumento é um mapeamento. Você provavelmente julgou mal o que está comendo o tempo todo.
Counter
passou a contar iteráveis grandes, em vez de contar muitos iteráveis. Contar um iterável de um milhão de strings será mais rápido do Counter
que com uma implementação manual. Se você quiser ligar update
com muitas iteráveis, poderá acelerar as coisas juntando-as a uma iterável itertools.chain
.
Contando as ocorrências de um item em uma lista
Para contar as ocorrências de apenas um item da lista, você pode usar count()
>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2
Contando as ocorrências de todos itens de uma lista também é conhecido como "calcular" uma lista ou criar um contador de contagem.
Contando todos os itens com count ()
Contar as ocorrências de itens em l
um pode simplesmente usar uma compreensão de lista e o count()
método
[[x,l.count(x)] for x in set(l)]
(ou similarmente com um dicionário dict((x,l.count(x)) for x in set(l))
)
Exemplo:
>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}
Contando todos os itens com Counter ()
Como alternativa, há a Counter
classe mais rápida da collections
biblioteca
Counter(l)
Exemplo:
>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})
Quanto mais rápido é o contador?
Eu verifiquei o quão mais rápido Counter
é para listas de cálculo. Eu tentei ambos os métodos com alguns valores de n
e parece queCounter
é mais rápido por um fator constante de aproximadamente 2.
Aqui está o script que eu usei:
from __future__ import print_function
import timeit
t1=timeit.Timer('Counter(l)', \
'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count(): ", t2.repeat(repeat=3,number=10000)
E a saída:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Counter
é muito mais rápido para listas maiores. O método de compreensão da lista é O (n ^ 2), Counter
deve ser O (n).
isinstance
. Portanto, se você tiver certeza dos dados com os quais está trabalhando, talvez seja melhor escrever uma função personalizada sem verificação de tipo e instância.
Outra maneira de obter o número de ocorrências de cada item, em um dicionário:
dict((i, a.count(i)) for i in a)
n * (number of different items)
operações, sem contar o tempo necessário para construir o conjunto. Usar collections.Counter
é realmente muito melhor.
i
, porque ela tentará inserir várias chaves do mesmo valor em um dicionário. dict((i, a.count(i)) for i in a)
list.count(x)
retorna o número de vezes que x
aparece em uma lista
consulte: http://docs.python.org/tutorial/datastructures.html#more-on-lists
Dado um item, como posso contar suas ocorrências em uma lista no Python?
Aqui está uma lista de exemplos:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Existe o list.count
método
>>> l.count('b')
4
Isso funciona bem para qualquer lista. As tuplas também têm esse método:
>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
E depois há coleções. Você pode despejar qualquer iterável em um contador, não apenas em uma lista, e o contador manterá uma estrutura de dados das contagens dos elementos.
Uso:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Os contadores são baseados em dicionários Python; suas chaves são os elementos; portanto, as chaves precisam ser laváveis. Eles são basicamente como conjuntos que permitem elementos redundantes neles.
collections.Counter
Você pode adicionar ou subtrair com iterables do seu contador:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
E você também pode executar operações de vários conjuntos com o contador:
>>> c2 = Counter(list('aabbxyz'))
>>> c - c2 # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2 # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2 # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2 # set intersection
Counter({'a': 2, 'b': 2})
Outra resposta sugere:
Por que não usar pandas?
O Pandas é uma biblioteca comum, mas não está na biblioteca padrão. Adicioná-lo como um requisito não é trivial.
Existem soluções internas para esse caso de uso no próprio objeto de lista e na biblioteca padrão.
Se seu projeto ainda não requer pandas, seria tolice torná-lo um requisito apenas para esta funcionalidade.
Comparei todas as soluções sugeridas (e algumas novas) com perfplot (um pequeno projeto meu).
Para matrizes grandes o suficiente, acontece que
numpy.sum(numpy.array(a) == 1)
é um pouco mais rápido que as outras soluções.
Conforme estabelecido anteriormente ,
numpy.bincount(a)
é o que você quer.
Código para reproduzir as parcelas:
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
2)
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
Se você pode usar pandas
, então value_counts
existe para resgatar.
>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1 3
4 2
3 1
2 1
dtype: int64
Também classifica automaticamente o resultado com base na frequência.
Se você deseja que o resultado esteja em uma lista de listas, faça o seguinte:
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Por que não usar Pandas?
import pandas as pd
l = ['a', 'b', 'c', 'd', 'a', 'd', 'a']
# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count
Resultado:
a 3
d 2
b 1
c 1
dtype: int64
Se você estiver procurando uma contagem de um elemento específico, diga a , tente:
my_count['a']
Resultado:
3
Hoje eu tive esse problema e rolei minha própria solução antes de pensar em verificar o SO. Este:
dict((i,a.count(i)) for i in a)
é muito, muito lento para grandes listas. Minha solução
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
é realmente um pouco mais rápido que a solução Counter, pelo menos para o Python 2.7.
# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
"""
:param items: iterable of hashable items to count
:type items: iterable
:returns: dict of counts like Py2.7 Counter
:rtype: dict
"""
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
# Python >= 2.2 (generators)
def count_sorted_list_items(items):
"""
:param items: sorted iterable of items to count
:type items: sorted iterable
:returns: generator of (item, count) tuples
:rtype: generator
"""
if not items:
return
elif len(items) == 1:
yield (items[0], 1)
return
prev_item = items[0]
count = 1
for item in items[1:]:
if prev_item == item:
count += 1
else:
yield (prev_item, count)
count = 1
prev_item = item
yield (item, count)
return
import unittest
class TestListCounters(unittest.TestCase):
def test_count_unsorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = count_unsorted_list_items(inp)
print inp, exp_outp, counts
self.assertEqual(counts, dict( exp_outp ))
inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )
def test_count_sorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = list( count_sorted_list_items(inp) )
print inp, exp_outp, counts
self.assertEqual(counts, exp_outp)
inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
# ... [(2,2), (4,1), (2,1)]
O mais rápido é usar um loop for e armazená-lo em um Dict.
import time
from collections import Counter
def countElement(a):
g = {}
for i in a:
if i in g:
g[i] +=1
else:
g[i] =1
return g
z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]
#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))
#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))
#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))
Resultado
#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0
itertools.groupby()
Outra possibilidade de obter a contagem de todos os elementos da lista pode ser por meio de itertools.groupby()
.
Com contagens "duplicadas"
from itertools import groupby
L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c'] # Input list
counts = [(i, len(list(c))) for i,c in groupby(L)] # Create value-count pairs as list of tuples
print(counts)
Devoluções
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Observe como ele combinou os três primeiros a
como o primeiro grupo, enquanto outros grupos de a
estão presentes mais abaixo na lista. Isso acontece porque a lista de entrada L
não foi classificada. Às vezes, isso pode ser um benefício se os grupos forem de fato separados.
Com contagens únicas
Se desejar contagens únicas de grupos, basta classificar a lista de entradas:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
Devoluções
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
Nota: Para criar contagens exclusivas, muitas das outras respostas fornecem código mais fácil e mais legível em comparação com a groupby
solução. Mas é mostrado aqui para desenhar um paralelo ao exemplo de contagem duplicada.
Foi sugerido o uso da contagem de números de um número , no entanto, ele funciona apenas para matrizes 1d com números inteiros não negativos . Além disso, a matriz resultante pode ser confusa (contém as ocorrências dos números inteiros de min a max da lista original e define como 0 os números inteiros ausentes).
Uma maneira melhor de fazer isso com numpy é usar a função exclusiva com o atributo return_counts
definido como True. Retorna uma tupla com uma matriz dos valores exclusivos e uma matriz das ocorrências de cada valor exclusivo.
# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True) # array([0, 1, 2, 3]), array([2, 3, 1, 2]
e então podemos emparelhá-los como
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
Também funciona com outros tipos de dados e "listas 2d", por exemplo
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
Embora seja uma pergunta muito antiga, mas como não encontrei uma linha, fiz uma.
# original numbers in list
l = [1, 2, 2, 3, 3, 3, 4]
# empty dictionary to hold pair of number and its count
d = {}
# loop through all elements and store count
[ d.update( {i:d.get(i, 0)+1} ) for i in l ]
print(d)
Você também pode usar o countOf
método de um módulo interno operator
.
>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3
countOf
é implementado? Como ele se compara ao mais óbvio list.count
(que se beneficia da implementação C)? Existem vantagens?
Pode não ser o mais eficiente, requer uma passagem extra para remover duplicatas.
Implementação funcional:
arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
retorna:
{('c', 1), ('b', 3), ('a', 2)}
ou retorne como dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
retorna:
{'b': 3, 'c': 1, 'a': 2}
sum([1 for elem in <yourlist> if elem==<your_value>])
Isso retornará a quantidade de ocorrências do seu_valor
se você deseja várias ocorrências para o elemento específico:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])
def countfrequncyinarray(arr1):
r=len(arr1)
return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)
l2=[1,"feto",["feto",1,["feto"]],['feto',[1,2,3,['feto']]]]
count=0
def Test(l):
global count
if len(l)==0:
return count
count=l.count("feto")
for i in l:
if type(i) is list:
count+=Test(i)
return count
print(Test(l2))
isso contará recursivamente ou procurará o item na lista, mesmo que ele esteja na lista de listas
mylist = [1,7,7,7,3,9,9,9,7,9,10,0] print sorted(set([i for i in mylist if mylist.count(i)>2]))