在Python中,给定一个项目,如何在列表中计算它的出现次数?
一个相关但不同的问题是计算集合中每个不同元素的出现次数,将字典或列表作为直方图结果而不是单个整数。有关该问题,请参阅使用字典统计列表中的项目。
在Python中,给定一个项目,如何在列表中计算它的出现次数?
一个相关但不同的问题是计算集合中每个不同元素的出现次数,将字典或列表作为直方图结果而不是单个整数。有关该问题,请参阅使用字典统计列表中的项目。
当前回答
我已经将所有建议的解决方案(以及一些新的解决方案)与perfplot(我的一个小项目)进行了比较。
清点一项
对于足够大的阵列,事实证明
numpy.sum(numpy.array(a) == 1)
比其他解决方案稍快。
清点所有项目
如前所述,
numpy.bincount(a)
是你想要的。
再现绘图的代码:
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,
)
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))
b = perfplot.bench(
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,
)
b.save("out.png")
b.show()
其他回答
我已经将所有建议的解决方案(以及一些新的解决方案)与perfplot(我的一个小项目)进行了比较。
清点一项
对于足够大的阵列,事实证明
numpy.sum(numpy.array(a) == 1)
比其他解决方案稍快。
清点所有项目
如前所述,
numpy.bincount(a)
是你想要的。
再现绘图的代码:
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,
)
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))
b = perfplot.bench(
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,
)
b.save("out.png")
b.show()
建议使用numpy的bincount,但它只适用于具有非负整数的1d数组。此外,生成的数组可能会令人困惑(它包含原始列表中从最小值到最大值的整数,并将缺失的整数设置为0)。
使用numpy的更好方法是使用属性return_counts设置为True的唯一函数。它返回一个元组,其中包含一个唯一值数组和每个唯一值的出现数组。
# 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]
然后我们可以将它们配对为
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
它也适用于其他数据类型和“2d列表”,例如。
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
要计算具有共同类型的不同元素的数量,请执行以下操作:
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')
给予
3,而不是6
# 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)]
虽然这是一个很古老的问题,但由于我没有找到一个单行,所以我做了一个。
# 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)
# {1: 1, 2: 2, 3: 3, 4: 1}