Dado un elemento, ¿cómo puedo contar sus ocurrencias en una lista en Python?
Si solo quieres el conteo de un artículo, usa el método de count
:
>>> [1, 2, 3, 4, 1, 4, 1].count(1) 3
No uses esto si quieres contar varios artículos. El count
llamadas en un bucle requiere un pase por separado sobre la lista para cada llamada de count
, lo que puede ser catastrófico para el rendimiento. Si desea contar todos los elementos, o incluso solo varios elementos, use Counter
, como se explica en las otras respuestas.
Si está utilizando Python 2.7 o 3 y desea un número de apariciones para cada elemento:
>>> from collections import Counter >>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red'] >>> Counter(z) Counter({'blue': 3, 'red': 2, 'yellow': 1})
Contando las ocurrencias de un elemento en una lista
Para contar las ocurrencias de un solo elemento de la lista puede usar count()
>>> l = ["a","b","b"] >>> l.count("a") 1 >>> l.count("b") 2
Contar las ocurrencias de todos los elementos de una lista también se conoce como “recuento” de una lista, o creación de un contador de recuento.
Contando todos los artículos con cuenta ()
Para contar las ocurrencias de elementos en l
, simplemente puede usar una lista de comprensión y el método count()
[[x,l.count(x)] for x in set(l)]
(o similarmente con un diccionario dict((x,l.count(x)) for x in set(l))
)
Ejemplo:
>>> 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 los artículos con contador ()
Alternativamente, está la clase Counter
más rápida de la biblioteca de collections
Counter(l)
Ejemplo:
>>> l = ["a","b","b"] >>> from collections import Counter >>> Counter(l) Counter({'b': 2, 'a': 1})
¿Cuánto más rápido es el contador?
Comprobé cuánto más rápido es el Counter
para las listas de recuento. Probé ambos métodos con unos pocos valores de n
y parece que Counter
es más rápido por un factor constante de aproximadamente 2.
Aquí está el guión que utilicé:
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)
Y la salida:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105] count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Otra forma de obtener el número de apariciones de cada elemento, en un diccionario:
dict((i, a.count(i)) for i in a)
list.count(x)
devuelve el número de veces que x
aparece en una lista
ver: http://docs.python.org/tutorial/datastructures.html#more-on-lists
Dado un elemento, ¿cómo puedo contar sus ocurrencias en una lista en Python?
Aquí hay una lista de ejemplos:
>>> l = list('aaaaabbbbcccdde') >>> l ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Ahí está el método list.count
>>> l.count('b') 4
Esto funciona bien para cualquier lista. Las tuplas también tienen este método:
>>> t = tuple('aabbbffffff') >>> t ('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f') >>> t.count('f') 6
collections.Counter
Y luego están las colecciones. Puede volcar cualquier iterable en un contador, no solo en una lista, y el contador conservará una estructura de datos de los conteos de los elementos.
Uso:
>>> from collections import Counter >>> c = Counter(l) >>> c['b'] 4
Los contadores se basan en los diccionarios de Python, sus claves son los elementos, por lo que las claves deben ser hashable. Básicamente son como conjuntos que permiten elementos redundantes en ellos.
collections.Counter
Puedes sumr o restar con iterables de tu contador:
>>> c.update(list('bbb')) >>> c['b'] 7 >>> c.subtract(list('bbb')) >>> c['b'] 4
Y también puede realizar operaciones de conjuntos múltiples con el 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})
Otra respuesta sugiere:
¿Por qué no usar pandas?
Pandas es una biblioteca común, pero no está en la biblioteca estándar. Agregarlo como un requisito no es trivial.
Hay soluciones integradas para este caso de uso en la lista de objetos en sí, así como en la biblioteca estándar.
Si su proyecto no requiere pandas, sería una tontería convertirlo en un requisito solo para esta funcionalidad.
Si desea contar todos los valores a la vez , puede hacerlo muy rápido utilizando matrices bincount
y bincount
siguiente manera
import numpy as np a = np.array([1, 2, 3, 4, 1, 4, 1]) np.bincount(a)
lo que da
>>> array([0, 3, 1, 1, 2])
He comparado todas las soluciones sugeridas (y algunas nuevas) con perfplot (un pequeño proyecto mío).
Para matrices suficientemente grandes, resulta que
numpy.sum(numpy.array(a) == 1)
Es un poco más rápido que las otras soluciones.
Como se estableció antes ,
numpy.bincount(a)
es lo que quieres
Código para reproducir las plots:
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, )
Si puedes usar pandas
, entonces value_counts
está ahí para el rescate.
>>> 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
También clasifica automáticamente el resultado en función de la frecuencia.
Si desea que el resultado esté en una lista de la lista, haga lo siguiente.
>>> pd.Series(a).value_counts().reset_index().values.tolist() [[1, 3], [4, 2], [3, 1], [2, 1]]
¿Por qué no 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
Salida:
a 3 d 2 b 1 c 1 dtype: int64
Si está buscando un recuento de un elemento en particular, diga a , intente:
my_count['a']
Salida:
3
# 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)]
Tuve este problema hoy y presenté mi propia solución antes de pensar en verificar SO. Esta:
dict((i,a.count(i)) for i in a)
Es muy, muy lento para listas grandes. Mi solución
def occurDict(items): d = {} for i in items: if i in d: d[i] = d[i]+1 else: d[i] = 1 return d
es en realidad un poco más rápido que la solución Counter, al menos para Python 2.7.
Para contar el número de elementos diversos que tienen un tipo común:
li = ['A0','c5','A8','A2','A5','c2','A3','A9'] print sum(1 for el in li if el[0]=='A' and el[1] in '01234')
da
3
, no 6
from collections import Counter country=['Uruguay', 'Mexico', 'Uruguay', 'France', 'Mexico'] count_country = Counter(country) output_list= [] for i in count_country: output_list.append([i,count_country[i]]) print output_list
Lista de salida:
[['Mexico', 2], ['France', 1], ['Uruguay', 2]]
Se sugirió usar bincount de numpy , sin embargo, solo funciona para matrices 1d con enteros no negativos . Además, la matriz resultante puede ser confusa (contiene las apariciones de los enteros de mínimo a máximo de la lista original, y establece en 0 los enteros faltantes).
Una mejor manera de hacerlo con numpy es usar la función única con el atributo return_counts
establecido en True. Devuelve una tupla con una matriz de los valores únicos y una matriz de las apariciones de cada valor único.
# 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]
y luego podemos emparejarlos como
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
También funciona con otros tipos de datos y “listas 2d”, por ejemplo,
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']] >>> dict(zip(*np.unique(a, return_counts=True))) {'a': 3, 'b': 3, 'c': 2}
itertools.groupby()
Una posibilidad adicional para obtener el recuento de todos los elementos de la lista podría ser mediante itertools.groupby()
.
Con cuentas “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)
Devoluciones
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Observe cómo combinó las tres primeras a
‘s como el primer grupo, mientras que otros grupos de a
están presentes más abajo en la lista. Esto sucede porque la lista de entrada L
no estaba ordenada. Esto puede ser un beneficio a veces si los grupos deberían estar separados.
Con cuentas únicas.
Si se desean conteos de grupos únicos, simplemente ordene la lista de entrada:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))] print(counts)
Devoluciones
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
También puede usar el método countOf
de un operator
módulo incorporado.
>>> import operator >>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1) 3
Puede que no sea el más eficiente, requiere un pase extra para eliminar duplicados.
Implementación funcional:
arr = np.array(['a','a','b','b','b','c']) print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
devoluciones :
{('c', 1), ('b', 3), ('a', 2)}
o devolver como dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
devoluciones :
{'b': 3, 'c': 1, 'a': 2}
Lo más rápido es usar un bucle for y almacenarlo en un 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
sum([1 for elem in if elem==])
Esto devolverá la cantidad de ocurrencias de su_valor
Si desea una serie de apariciones para el elemento en particular:
>>> 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)