Bir öğe verildiğinde, Python'daki bir listedeki oluşumlarını nasıl sayabilirim?
Bir öğe verildiğinde, Python'daki bir listedeki oluşumlarını nasıl sayabilirim?
Yanıtlar:
Yalnızca bir öğenin sayılmasını istiyorsanız, count
yöntemi kullanın :
>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3
Birden fazla öğe saymak istiyorsanız bunu kullanmayın. Arayan count
bir döngü içinde her için liste üzerinde ayrı bir geçiş gerektirir count
performans için felaket olabilir çağrı. Tüm öğeleri ve hatta birden fazla öğeyi saymak istiyorsanız Counter
, diğer yanıtlarda açıklandığı gibi kullanın .
Counter
Python 2.7 veya 3.x kullanıyorsanız ve her bir öğe için gerçekleşme sayısını istiyorsanız kullanın :
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
isinstance
. Bu nedenle, üzerinde çalıştığınız verilerden eminseniz, tür ve örnek denetimi olmadan özel bir işlev yazmak daha iyi olabilir.
isinstance
çağırıyor? Milyonlarca dizede bile, çağrı , argümanının bir eşleme olup olmadığını kontrol etmek için Counter
sadece bir isinstance
çağrı içerir . Büyük olasılıkla tüm zaman boyunca ne yediğinizi yanlış değerlendirdiniz.
Counter
birçok tekrarlanabilir saymak yerine büyük tekrarlanabilir sayımlara dönüştü. Bir milyon telli yinelenebilir saymak, Counter
manuel bir uygulamadan daha hızlı gidecektir . Çok update
sayıda yinelemeyle çağrı yapmak istiyorsanız, şeyleri tek bir yinelemeye katılarak hızlandırabilirsiniz itertools.chain
.
Listedeki bir öğenin oluşumlarını sayma
Yalnızca bir liste öğesinin oluşumlarını saymak için kullanabilirsiniz count()
>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2
Bir listedeki tüm öğelerin oluşumlarını saymak, bir listeyi "saymak" veya bir sayım sayacı oluşturmak olarak da bilinir.
Count () ile tüm öğeleri sayma
Birindeki öğelerin oluşumlarını saymak için l
bir liste kavrayışı ve count()
yöntemi kullanabilirsiniz.
[[x,l.count(x)] for x in set(l)]
(veya bir sözlükle benzer şekilde dict((x,l.count(x)) for x in set(l))
)
Misal:
>>> 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}
Sayaç () ile tüm öğeleri sayma
Alternatif olarak, kütüphaneden daha hızlı Counter
sınıf varcollections
Counter(l)
Misal:
>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})
Counter ne kadar hızlı?
Counter
Listeleri yazmak için ne kadar hızlı olduğunu kontrol ettim . Her iki yöntemi de birkaç değerle denedim n
ve Counter
yaklaşık 2'lik sabit bir faktörle daha hızlı olduğu görülüyor .
İşte kullandığım komut dosyası:
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)
Ve çıktı:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Counter
olduğu yolu daha hızlı daha büyük listeleri. Liste anlama yöntemi O (n ^ 2), Counter
O (n) olmalıdır.
isinstance
. Bu nedenle, üzerinde çalıştığınız verilerden eminseniz, tür ve örnek denetimi olmadan özel bir işlev yazmak daha iyi olabilir.
Sözlükteki her bir öğenin tekrarlama sayısını almanın başka bir yolu:
dict((i, a.count(i)) for i in a)
n * (number of different items)
bu seti inşa için gereken süreyi saymazsak, işlemleri. Kullanımı collections.Counter
gerçekten çok daha iyi.
i
, çünkü sözlükte aynı değere sahip birden fazla anahtar girmeye çalışır. dict((i, a.count(i)) for i in a)
list.count(x)
x
listede kaç kez görüntülendiğini döndürür
bkz. http://docs.python.org/tutorial/datastructures.html#more-on-lists
Bir öğe verildiğinde, Python'daki bir listedeki oluşumlarını nasıl sayabilirim?
İşte bir örnek liste:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Orada list.count
yöntem
>>> l.count('b')
4
Bu herhangi bir liste için iyi çalışıyor. Tuples'ın da bu yöntemi var:
>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
Bir de koleksiyonlar var. Yinelenebilir herhangi bir sayacı yalnızca bir listeye değil, bir Sayaca da dökebilirsiniz ve Sayaç, öğelerin sayımlarının veri yapısını korur.
Kullanımı:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Sayaçlar Python sözlüklerine dayanır, anahtarları öğelerdir, bu nedenle anahtarların yıkanabilir olması gerekir. Temel olarak, gereksiz elemanlara izin veren setler gibidirler.
collections.Counter
Sayacınızdan tekrarlanabilir öğeler ekleyebilir veya çıkarabilirsiniz:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
Sayaçla da çoklu ayar işlemleri yapabilirsiniz:
>>> 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})
Başka bir cevap şöyle:
Neden panda kullanmıyorsunuz?
Pandalar ortak bir kütüphanedir, ancak standart kütüphanede değildir. Bir gereksinim olarak eklemek önemsiz değildir.
Liste nesnesinin kendisinde ve standart kitaplıkta bu kullanım senaryosu için yerleşik çözümler vardır.
Projeniz zaten panda gerektirmiyorsa, sadece bu işlevsellik için bir gereksinim haline getirmek aptalca olacaktır.
Önerilen tüm çözümleri (ve birkaç yeni çözümü) perfplot (küçük bir proje) ile karşılaştırdım.
Yeterince büyük diziler için,
numpy.sum(numpy.array(a) == 1)
diğer çözümlerden biraz daha hızlıdır.
numpy.bincount(a)
istediğin şey bu.
Arsaları yeniden oluşturmak için kod:
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,
)
Eğer kullanabiliyorsanız pandas
, value_counts
kurtarma için oradasınız.
>>> 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
Sonucu otomatik olarak frekansa göre sıralar.
Sonucun bir liste listesinde yer almasını istiyorsanız, aşağıdakileri yapın
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Neden Pandaları kullanmıyorsunuz?
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
Çıktı:
a 3
d 2
b 1
c 1
dtype: int64
Belirli bir elemanın bir sayım için arıyorsanız, demek bir deneyin:
my_count['a']
Çıktı:
3
Bugün bu sorunu yaşadım ve SO'yu kontrol etmeyi düşünmeden önce kendi çözümümü yedim. Bu:
dict((i,a.count(i)) for i in a)
büyük listeler için gerçekten çok yavaş. Çözümüm
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
aslında en azından Python 2.7 için Counter çözümünden biraz daha hızlı.
# 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)]
En hızlı bir for döngüsü kullanmak ve bir Dict içinde saklamaktır.
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))
Sonuç
#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()
Listedeki tüm öğelerin sayısını elde etmek için Antoher olasılığı vasıtasıyla olabilir itertools.groupby()
.
"Yinelenen" sayımlarla
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)
İadeler
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
İlk üç a
grubu ilk grup olarak nasıl birleştirdiğine dikkat edin , diğer gruplar a
ise listede daha aşağıda yer alıyor. Bu, giriş listesi L
sıralanmadığı için olur. Grupların ayrı olması gerektiğinde bu bazen bir fayda olabilir.
Benzersiz sayımlarla
Benzersiz grup sayımları isteniyorsa, giriş listesini sıralamanız yeterlidir:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
İadeler
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
Not: Benzersiz sayımlar oluşturmak için, diğer yanıtların çoğu groupby
çözüme kıyasla daha kolay ve daha okunabilir kod sağlar . Ancak burada yinelenen sayım örneğine bir paralel çizmek gösterilmiştir.
Numpy'nin bincount'unun kullanılması önerildi , ancak yalnızca negatif olmayan tamsayılara sahip 1d diziler için çalışır . Ayrıca, sonuçta ortaya çıkan dizi kafa karıştırıcı olabilir (orijinal listenin min'den maksimuma kadar tamsayıların oluşumunu içerir ve eksik tamsayıları 0'a ayarlar).
Numpy ile yapmanın daha iyi bir yolu, benzersiz işlevi return_counts
True olarak ayarlanmış şekilde kullanmaktır. Benzersiz değerlerin bir dizisini ve her benzersiz değerin oluşumlarının bir dizisini içeren bir grup döndürür.
# 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]
ve sonra onları
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
Ayrıca diğer veri türleri ve "2d listeleri" ile çalışır, ör.
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
Her ne kadar çok eski bir soru olsa da, bir astar bulamadım, bir tane yaptım.
# 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)
Yerleşik countOf
bir modülün yöntemini de kullanabilirsiniz operator
.
>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3
countOf
uygulanır? Daha açık olanla nasıl karşılaştırılır list.count
(C uygulamasından hangi faydalar sağlanır)? Herhangi bir avantajı var mı?
En verimli olmayabilir, kopyaları kaldırmak için ekstra bir geçiş gerektirir.
İşlevsel uygulama:
arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
İadeler :
{('c', 1), ('b', 3), ('a', 2)}
veya şu şekilde iade edin dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
İadeler :
{'b': 3, 'c': 1, 'a': 2}
sum([1 for elem in <yourlist> if elem==<your_value>])
Bu, değerinizin gerçekleşme miktarını döndürür
belirli bir öğe için birkaç tekrarlama yapmak istiyorsanız:
>>> 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))
bu, yinelenen sayım yapar veya liste listesinde olsa bile listedeki öğeyi arar
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]))