Odpowiedzi:
Jeśli chcesz policzyć tylko jeden przedmiot, użyj count
metody:
>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3
Nie używaj tego, jeśli chcesz policzyć wiele przedmiotów. Wywołanie count
w pętli wymaga osobnego przejścia przez listę dla każdego count
połączenia, co może mieć katastrofalny wpływ na wydajność. Jeśli chcesz policzyć wszystkie elementy, a nawet tylko kilka elementów, użyj Counter
, jak wyjaśniono w innych odpowiedziach.
Użyj, Counter
jeśli używasz języka Python 2.7 lub 3.x i chcesz liczbę wystąpień każdego elementu:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
isinstance
. Jeśli więc masz pewność co do danych, z którymi pracujesz, może być lepiej napisać niestandardową funkcję bez sprawdzania typu i instancji.
isinstance
połączenia? Nawet w przypadku milionów ciągów wywołanie Counter
obejmuje tylko jedno isinstance
wywołanie, aby sprawdzić, czy jego argumentem jest odwzorowanie. Najprawdopodobniej źle oceniłeś, co jesz przez cały czas.
Counter
polegały na liczeniu dużych iteracji, a nie liczeniu wielu iteracji. Liczenie milionowej iterowalnej iteracji pójdzie szybciej Counter
niż przy ręcznej implementacji. Jeśli chcesz zadzwonić update
z wieloma iteratorami, możesz być w stanie przyspieszyć, łącząc je w jeden iterowalny z itertools.chain
.
Zliczanie wystąpień jednego elementu na liście
Do zliczania wystąpień tylko jednego elementu listy można użyć count()
>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2
Liczenie wystąpień wszystkich elementów na liście jest również znane jako „liczenie” listy lub tworzenie licznika liczb.
Zliczanie wszystkich elementów za pomocą count ()
Aby policzyć występowanie elementów w l
jednym, wystarczy po prostu skorzystać ze zrozumienia listy i count()
metody
[[x,l.count(x)] for x in set(l)]
(lub podobnie ze słownikiem dict((x,l.count(x)) for x in set(l))
)
Przykład:
>>> 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}
Liczenie wszystkich elementów za pomocą Counter ()
Alternatywnie istnieje szybsza Counter
klasa z collections
biblioteki
Counter(l)
Przykład:
>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})
O ile szybciej działa Counter?
Sprawdziłem, o ile szybsze Counter
jest tworzenie list liczników. Wypróbowałem obie metody z kilkoma wartościami n
i wydaje się, że Counter
jest to szybsze o stały współczynnik około 2.
Oto skrypt, którego użyłem:
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)
A wynik:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Counter
jest znacznie szybszy dla większych list. Metodą rozumienia listy jest O (n ^ 2), Counter
powinna być O (n).
isinstance
. Jeśli więc masz pewność co do danych, z którymi pracujesz, może być lepiej napisać niestandardową funkcję bez sprawdzania typu i instancji.
Inny sposób na uzyskanie liczby wystąpień każdego elementu w słowniku:
dict((i, a.count(i)) for i in a)
n * (number of different items)
operacje, nie licząc czasu potrzebnego na zbudowanie zestawu. Korzystanie collections.Counter
jest naprawdę dużo lepsze.
i
, ponieważ spróbuje wprowadzić wiele kluczy o tej samej wartości w słowniku. dict((i, a.count(i)) for i in a)
list.count(x)
zwraca liczbę pojawień x
się na liście
patrz: http://docs.python.org/tutorial/datastructures.html#more-on-lists
W przypadku danego elementu, jak mogę policzyć jego wystąpienia na liście w Pythonie?
Oto przykładowa lista:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Jest list.count
metoda
>>> l.count('b')
4
Działa to dobrze dla każdej listy. Krotki mają również tę metodę:
>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
A potem są kolekcje. Licznik. Możesz zrzucić dowolny iterowalny licznik, a nie tylko listę, a licznik zachowa strukturę danych zliczeń elementów.
Stosowanie:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Liczniki oparte są na słownikach Pythona, ich klucze są elementami, więc klucze muszą być możliwe do skrócenia. Zasadniczo są to zestawy, które pozwalają na nadmiarowe elementy.
collections.Counter
Możesz dodać lub odjąć za pomocą iteracji z twojego licznika:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
Możesz także wykonywać operacje na wielu ustawieniach za pomocą licznika:
>>> 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})
Inna odpowiedź sugeruje:
Dlaczego nie skorzystać z pand?
Pandy to popularna biblioteka, ale nie ma jej w standardowej bibliotece. Dodanie go jako wymagania nie jest trywialne.
Istnieją wbudowane rozwiązania dla tego przypadku użycia w samym obiekcie listy, a także w bibliotece standardowej.
Jeśli twój projekt nie wymaga już pand, głupotą byłoby uczynienie go wymogiem tylko dla tej funkcjonalności.
Porównałem wszystkie sugerowane rozwiązania (i kilka nowych) z perfplot ( mój mały projekt).
Okazuje się, że w przypadku wystarczająco dużych tablic
numpy.sum(numpy.array(a) == 1)
jest nieco szybszy niż inne rozwiązania.
numpy.bincount(a)
jest tym, czego chcesz.
Kod do odtworzenia wykresów:
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,
)
Jeśli chcesz policzyć wszystkie wartości naraz , możesz to zrobić bardzo szybko, używając tablic numpy i bincount
w następujący sposób
import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)
co daje
>>> array([0, 3, 1, 1, 2])
Jeśli możesz użyć pandas
, to value_counts
jest tam na ratunek.
>>> 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
Automatycznie sortuje również wynik na podstawie częstotliwości.
Jeśli chcesz, aby wynik znalazł się na liście, wykonaj następujące czynności
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Dlaczego nie skorzystać z pand?
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
Wynik:
a 3
d 2
b 1
c 1
dtype: int64
Jeśli szukasz liczby konkretnego elementu, powiedz a , spróbuj:
my_count['a']
Wynik:
3
Miałem dzisiaj ten problem i opracowałem własne rozwiązanie, zanim pomyślałem o sprawdzeniu SO. To:
dict((i,a.count(i)) for i in a)
jest naprawdę bardzo powolny w przypadku dużych list. Moje rozwiązanie
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
jest w rzeczywistości nieco szybszy niż rozwiązanie Counter, przynajmniej w Pythonie 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)]
Najszybszym jest użycie pętli for i przechowywanie jej w 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))
Wynik
#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()
Istnieje również możliwość uzyskania liczby wszystkich elementów na liście za pomocą itertools.groupby()
.
Liczy się „duplikat”
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)
Zwroty
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Zauważ, jak połączyło pierwsze trzy a
jako pierwszą grupę, podczas gdy inne grupy a
znajdują się w dalszej części listy. Dzieje się tak, ponieważ lista wejściowa L
nie została posortowana. Może to być czasem korzystne, jeśli grupy faktycznie powinny być oddzielne.
Z unikalnymi liczbami
Jeśli wymagane są unikalne liczby grup, wystarczy posortować listę danych wejściowych:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
Zwroty
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
Uwaga: W przypadku tworzenia unikalnych zliczeń wiele innych odpowiedzi zapewnia łatwiejszy i bardziej czytelny kod w porównaniu do groupby
rozwiązania. Ale pokazano tutaj, aby narysować równolegle do duplikatu przykładu zliczania.
Sugerowano użycie liczby binarnej numpy , jednak działa ona tylko dla tablic 1d z nieujemnymi liczbami całkowitymi . Również wynikowa tablica może być myląca (zawiera występowanie liczb całkowitych od min do maks. Oryginalnej listy i ustawia na 0 brakujące liczby całkowite).
Lepszym sposobem na zrobienie tego za pomocą numpy jest użycie unikalnej funkcji z atrybutem return_counts
ustawionym na True. Zwraca krotkę z tablicą unikalnych wartości i tablicą występowania każdej unikalnej wartości.
# 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]
a następnie możemy je sparować jako
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
Działa również z innymi typami danych i „listami 2d”, np
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
Chociaż jest to bardzo stare pytanie, ale ponieważ nie znalazłem jednej wkładki, zrobiłem jedną.
# 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)
Możesz także użyć countOf
metody wbudowanego modułu operator
.
>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3
countOf
jest wdrażany? Jak wypada w porównaniu z bardziej oczywistymi list.count
(jakie korzyści z wdrożenia C)? Czy są jakieś zalety?
Może nie być najbardziej wydajny, wymaga dodatkowego przejścia, aby usunąć duplikaty.
Wdrożenie funkcjonalne:
arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
zwroty :
{('c', 1), ('b', 3), ('a', 2)}
lub wróć jako dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
zwroty :
{'b': 3, 'c': 1, 'a': 2}
sum([1 for elem in <yourlist> if elem==<your_value>])
Zwróci to liczbę wystąpień twojej wartości
jeśli chcesz mieć kilka wystąpień dla danego elementu:
>>> 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))
spowoduje to rekurencyjne zliczanie lub wyszukiwanie elementu na liście, nawet jeśli jest on na liście list
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]))