如何计算列表项的出现次数?

给定一个项目,如何在Python中计算它在列表中的出现次数?


一个相关但不同的问题是计算集合中每个不同元素的出现次数,获取字典或列表作为直方图结果而不是单个整数。关于这个问题,请参阅使用字典计算列表中的项目

2668440 次浏览

如果您只想要单个项目的计数,请使用count方法:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)3

重要提示:如果您正在计算多个不同的项目,这将非常慢

每个count调用遍历整个n元素列表。在循环中调用countn次意味着n * n次总检查,这可能会对性能造成灾难性影响。

如果您想计算多个项目,请使用#0,它只执行n总检查。

list.count(x)返回x在列表中出现的次数

请看:http://docs.python.org/tutorial/datastructures.html#more-on-lists

如果您使用Python 2.7或3. x并且想要每个元素的出现次数,请使用#0

>>> from collections import Counter>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']>>> Counter(z)Counter({'blue': 3, 'red': 2, 'yellow': 1})
# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)from collections import defaultdictdef 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] += 1return 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:returnelif len(items) == 1:yield (items[0], 1)returnprev_item = items[0]count = 1for item in items[1:]:if prev_item == item:count += 1else:yield (prev_item, count)count = 1prev_item = itemyield (item, count)return

import unittestclass 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, countsself.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, countsself.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)]

计算具有共同类型的不同元素的数量:

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

另一种获取字典中每个项目出现次数的方法:

dict((i, a.count(i)) for i in a)

我今天遇到了这个问题,在我想检查SO之前推出了我自己的解决方案。这:

dict((i,a.count(i)) for i in a)

对于大名单来说是非常非常慢的我的解决方案

def occurDict(items):d = {}for i in items:if i in d:d[i] = d[i]+1else:d[i] = 1return d

实际上比计数器解决方案快一点,至少对于Python 2.7来说是这样。

如果您想一次计算所有值,您可以使用numpy数组和bincount快速完成,如下所示

import numpy as npa = np.array([1, 2, 3, 4, 1, 4, 1])np.bincount(a)

这给了

>>> array([0, 3, 1, 1, 2])

计算列表中一项的出现次数

为了计算一个列表项的出现次数,您可以使用count()

>>> l = ["a","b","b"]>>> l.count("a")1>>> l.count("b")2

计算列表中所有项的出现次数也称为“统计”列表,或创建计数计数器。

计数所有的项目与计数()

要计算l中项目的出现次数,可以简单地使用列表理解和count()方法

[[x,l.count(x)] for x in set(l)]

(或者类似于字典dict((x,l.count(x)) for x in set(l))

示例:

>>> 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}

计数所有项目与计数器()

或者,有collections库中更快的Counter

Counter(l)

示例:

>>> l = ["a","b","b"]>>> from collections import Counter>>> Counter(l)Counter({'b': 2, 'a': 1})

计数器有多快?

我检查了Counter在计算列表时的速度有多快。我用n的几个值尝试了这两种方法,似乎Counter的速度快了大约2的常数因子。

这是我使用的脚本:

from __future__ import print_functionimport 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)

输出:

Counter():  [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]count():    [7.779430688009597, 7.962715800967999, 8.420845870045014]

给定一个项目,如何在Python中计算它在列表中的出现次数?

下面是一个示例列表:

>>> l = list('aaaaabbbbcccdde')>>> l['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']

list.count

list.count方法

>>> l.count('b')4

这适用于任何列表。元组也有这个方法:

>>> t = tuple('aabbbffffff')>>> t('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')>>> t.count('f')6

collections.Counter

你可以将任何可迭代对象转储到计数器中,而不仅仅是列表,计数器将保留元素计数的数据结构。

用法:

>>> from collections import Counter>>> c = Counter(l)>>> c['b']4

计数器基于Python字典,它们的键是元素,所以键需要是可散列的。它们基本上就像允许冗余元素进入它们的集合。

collections.Counter的进一步使用

您可以从计数器中添加或减去可迭代对象:

>>> c.update(list('bbb'))>>> c['b']7>>> c.subtract(list('bbb'))>>> c['b']4

您也可以使用计数器进行多集操作:

>>> c2 = Counter(list('aabbxyz'))>>> c - c2                   # set differenceCounter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})>>> c + c2                   # addition of all elementsCounter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})>>> c | c2                   # set unionCounter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})>>> c & c2                   # set intersectionCounter({'a': 2, 'b': 2})

愚蠢的回答,总和

有很好的内置答案,但这个例子有点启发性。这里我们总结所有字符c等于'b'的情况:

>>> sum(c == 'b' for c in l)4

对于这个用例来说不是很好,但是如果你需要在情况为True的情况下有一个迭代数,那么求和布尔结果是非常好的,因为True等价于1

为什么不是熊猫?

另一个答案是:

为什么不用熊猫?

Pandas是一个通用库,但它不在标准库中。将其添加为需求并非易事。

列表对象本身以及标准库中都有针对此用例的内置解决方案。

如果您的项目还不需要Pandas,那么仅将其作为此功能的要求将是愚蠢的。

也可以使用内置模块#1的方法#0

>>> import operator>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)3

为什么不使用Pandas?

import pandas as pd
my_list = ['a', 'b', 'c', 'd', 'a', 'd', 'a']
# converting the list to a Series and counting the valuesmy_count = pd.Series(my_list).value_counts()my_count

输出:

a    3d    2b    1c    1dtype: int64

如果您正在寻找特定元素的计数,例如一个,请尝试:

my_count['a']

输出:

3
sum([1 for elem in <yourlist> if elem==<your_value>])

这将返回your_value发生的数量

我已经将所有建议的解决方案(以及一些新的解决方案)与灌流图(我的一个小项目)进行了比较。

计算一个项目

对于足够大的数组,事实证明

numpy.sum(numpy.array(a) == 1)

它比其他解决方案更快。

在此处输入图片描述

计算所有项目

如前所述

numpy.bincount(a)

就是你想要的。

在此处输入图片描述


重现情节的代码:

from collections import Counterfrom collections import defaultdictimport numpyimport operatorimport pandasimport 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]+1else:d[i] = 1return d

def count_unsorted_list_items(items):counts = defaultdict(int)for item in items:counts[item] += 1return 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 Counterfrom collections import defaultdictimport numpyimport operatorimport pandasimport 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] + 1else:d[i] = 1return d

def count_unsorted_list_items(items):counts = defaultdict(int)for item in items:counts[item] += 1return 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()

如果你可以使用pandas,那么value_counts就在那里进行救援。

>>> import pandas as pd>>> a = [1, 2, 3, 4, 1, 4, 1]>>> pd.Series(a).value_counts()1    34    23    12    1dtype: int64

它还会根据频率自动对结果进行排序。

如果您希望结果在列表列表中,请执行以下操作

>>> pd.Series(a).value_counts().reset_index().values.tolist()[[1, 3], [4, 2], [3, 1], [2, 1]]

可能不是最有效的,需要额外的通道来删除重复项。

功能实现:

arr = np.array(['a','a','b','b','b','c'])print(set(map(lambda x  : (x , list(arr).count(x)) , arr)))

退货:

{('c', 1), ('b', 3), ('a', 2)}

或返回为dict

print(dict(map(lambda x  : (x , list(arr).count(x)) , arr)))

退货:

{'b': 3, 'c': 1, 'a': 2}
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)

建议使用numpy的宾计数,但它仅适用于具有非负整数的1d数组。此外,结果数组可能会令人困惑(它包含原始列表中从min到max的整数的出现次数,并将缺失的整数设置为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}

计数itertools.groupby()的所有元素

Antoher获取列表中所有元素的计数的可能性可以通过itertools.groupby()

与“重复”计数

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 tuplesprint(counts)

退货

[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]

请注意它如何将前三个a组合为第一组,而a的其他组则出现在列表的下方。这是因为输入列表L没有排序。如果这些组实际上应该是分开的,有时这可能是一个好处。

具有独特的计数

如果需要唯一的组计数,只需对输入列表进行排序:

counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]print(counts)

退货

[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]

备注:对于创建唯一计数,与groupby解决方案相比,许多其他答案提供了更容易且更可读的代码。但这里显示的是与重复计数示例的并行。

以下是三种解决方案:

最快的方法是使用for循环并将其存储在DICT中。

import timefrom collections import Counter

def countElement(a):g = {}for i in a:if i in g:g[i] +=1else:g[i] =1return 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 - Fasterst = 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 - Fastst = 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 - Slowst = 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))

结果

#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

虽然这是一个非常古老的问题,因为我没有找到一个班轮,我做了一个。

# original numbers in listl = [1, 2, 2, 3, 3, 3, 4]
# empty dictionary to hold pair of number and its countd = {}
# 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}

我将使用filter(),以Lukasz为例:

>>> lst = [1, 2, 3, 4, 1, 4, 1]>>> len(filter(lambda x: x==1, lst))3

给定一个list x

 import numpy as npX = [1, -1, 1, -1, 1]

显示此列表中元素的i:频率(i)的字典是:

{i:X.count(i) for i in np.unique(X)}

输出:

{-1: 2, 1: 3}

使用%timeit查看哪个操作更有效。np.array计数操作应该更快。

 from collections import Countermylist = [1,7,7,7,3,9,9,9,7,9,10,0]types_counts=Counter(mylist)print(types_counts)
test = [409.1, 479.0, 340.0, 282.4, 406.0, 300.0, 374.0, 253.3, 195.1, 269.0, 329.3, 250.7, 250.7, 345.3, 379.3, 275.0, 215.2, 300.0]
for i in test:print('{} numbers {}'.format(i, test.count(i)))

或者,您也可以自己实现计数器。这是我的做法:

item_list = ['me', 'me', 'you', 'you', 'you', 'they']
occ_dict = {}
for item in item_list:if item not in occ_dict:occ_dict[item] = 1else:occ_dict[item] +=1
print(occ_dict)

输出:{'me': 2, 'you': 3, 'they': 1}

mot = ["compte", "france", "zied"]lst = ["compte", "france", "france", "france", "france"]dict((x, lst.count(x)) for x in set(mot))

这给了

{'compte': 1, 'france': 4, 'zied': 0}
import pandas as pdtest = [409.1, 479.0, 340.0, 282.4, 406.0, 300.0, 374.0, 253.3, 195.1, 269.0, 329.3, 250.7, 250.7, 345.3, 379.3, 275.0, 215.2, 300.0]
#turning the list into a temporary dataframetest  = pd.DataFrame(test)
#using the very convenient value_counts() functiondf_counts = test.value_counts()df_counts

然后您可以使用df_counts.indexdf_counts.values来获取数据。

x = ['Jess', 'Jack', 'Mary', 'Sophia', 'Karen','Addison', 'Joseph','Jack', 'Jack', 'Eric', 'Ilona', 'Jason']the_item = input('Enter the item that you wish to find : ')how_many_times = 0for occurrence in x:if occurrence == the_item :how_many_times += 1print('The occurrence of', the_item, 'in', x,'is',how_many_times)

创建了一个重复名称“Jack”的名称列表。为了检查它的发生,我在名为x的列表中运行了一个for循环。在每次迭代中,如果循环变量获得与从用户接收并存储在变量the_item中的值相同的值,则变量how_many_times将增加1。在获得一些值之后……我们打印how_many_times,它存储了单词“Jack”出现的值