如何计算无序列表中元素的频率?


237

我需要找到无序列表中元素的频率

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

输出->

b = [4,4,2,1,2]

我也想从中删除重复项

a = [1,2,3,4,5]

是否总是像该示例那样订购?
Farinha 2010年

@彼得。是的,您已出于发布目的对列表进行了排序。列表会一直排序吗?
S.Lott

2
不,列表不会总是排序。这不是功课。
布鲁斯

我正在尝试绘制网络度分布图。
布鲁斯

5
@Peter:请使用有用的信息更新您的问题。请不要在问题中添加评论-您是问题的所有者,可以将其修正为完整清晰的内容。
S.Lott

Answers:


147

注意:您应该在使用之前对列表进行排序groupby

如果列表是有序列表,则可以groupbyitertools包中使用。

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
from itertools import groupby
[len(list(group)) for key, group in groupby(a)]

输出:

[4, 4, 2, 1, 2]

很好,使用groupby。我想知道它的效率与dict方法的关系
Eli Bendersky 2010年

32
python groupby在看到的值更改时会创建新的组。在这种情况下,1,1,1,2,1,1,1]将返回[3,1,3]。如果您期望[6,1],那么请确保在使用groupby之前对数据进行排序。
埃文(Evan)2010年

4
@CristianCiupitu: sum(1 for _ in group)
马丁·彼得斯

6
这不是解决方案。输出不会告诉您计数了什么。
buhtz '16

8
[(key, len(list(group))) for key, group in groupby(a)]{key: len(list(group)) for key, group in groupby(a)}@buhtz
Eric Pauley

532

在Python 2.7(或更高版本)中,您可以使用collections.Counter

import collections
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
counter=collections.Counter(a)
print(counter)
# Counter({1: 4, 2: 4, 3: 2, 5: 2, 4: 1})
print(counter.values())
# [4, 4, 2, 1, 2]
print(counter.keys())
# [1, 2, 3, 4, 5]
print(counter.most_common(3))
# [(1, 4), (2, 4), (3, 2)]

如果您使用的是Python 2.6或更早版本,则可以在此处下载。


1
@unutbu:如果我有三个列表,a,b,c,而a和b保持不变,但是c改变了?如何计算a和c相同的c的值?
ThePredator 2014年

@Srivatsan:我不了解情况。请发布一个新的问题,在这里您可以详细说明。
unutbu 2014年

1
有没有办法从计数器对象中提取字典{1:4,2:4,3:2,5:2,4:1}?
帕万2015年

7
@Pavan:collections.Counter是的子类dict。您可以像普通字典一样使用它。但是,如果您确实想要字典,则可以使用将其转换为字典dict(counter)
unutbu 2015年

1
在3.6中也可以使用,因此假定大于2.7的值
kpierce8 '17

108

Python 2.7+引入了Dictionary Comprehension。从列表中构建字典将使您获得计数并消除重复项。

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> d = {x:a.count(x) for x in a}
>>> d
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
>>> a, b = d.keys(), d.values()
>>> a
[1, 2, 3, 4, 5]
>>> b
[4, 4, 2, 1, 2]

这与字符串列表(而不是整数)(如所提出的原始问题)相反,非常有效。
Glen Selle

15
使用设置更快:{x:a.count(x) for x in set(a)}
stenci

45
这是非常低效的a.count()做了完整的横移中的每个元素a,使之成为一个O(N ^ 2)二次型的方法。collections.Counter()更有效的,因为它以线性时间(O(N))进行计数。从数量上讲,这意味着对于长度为1000的列表,此方法将执行1百万步,而对于长度为1000的列表,则仅执行1000步Counter(),而Counter对于列表中的一百万个项目仅需要10 ^ 6步,依此类推
Martijn Pieters

3
@stenci:当然可以,但是a.count()完全使用它的恐惧使在那儿使用电视机的效率相形见war 。
马丁·彼得斯

2
@MartijnPieters还有一个理由减少使用它的次数:)
stenci

48

计算出场次数:

from collections import defaultdict

appearances = defaultdict(int)

for curr in a:
    appearances[curr] += 1

删除重复项:

a = set(a) 

1
+1为collections.defaultdict。另外,在python 3.x中,查找collections.Counter。它与collections.defaultdict(int)相同。
hughdbrown 2010年

2
@hughdbrown实际上Counter可以使用多种数字类型,包括floatDecimal,而不仅仅是int
克里斯蒂安·丘皮图

28

在Python 2.7+中,您可以使用collections.Counter对项目进行计数

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>>
>>> from collections import Counter
>>> c=Counter(a)
>>>
>>> c.values()
[4, 4, 2, 1, 2]
>>>
>>> c.keys()
[1, 2, 3, 4, 5]

1
计数器比默认字典慢得多,默认字典比手动使用字典慢得多。
乔纳森·雷

@JonathanRay,不再有用,stackoverflow.com/ a/27802189/1382487 。
wsaleem

25

计算元素的频率最好用字典来完成:

b = {}
for item in a:
    b[item] = b.get(item, 0) + 1

要删除重复项,请使用一组:

a = list(set(a))

3
@phkahler:我的只会比这更好一点。如果可以通过少量更改来改善此问题,那么我就不值得发布单独的答案。SO的重点是获得最佳答案。我可以简单地对此进行编辑,但是我希望允许原始作者有机会进行自己的改进。
S.Lott

1
@ S.Lott该代码更加干净,无需导入defaultdict
bstrauch24

为什么不预先初始化b : b = {k:0 for k in a}
DylanYoung

20

这是另一个简洁的替代方法itertools.groupby,它也适用于无序输入:

from itertools import groupby

items = [5, 1, 1, 2, 2, 1, 1, 2, 2, 3, 4, 3, 5]

results = {value: len(list(freq)) for value, freq in groupby(sorted(items))}

结果

{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}

16

你可以这样做:

import numpy as np
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
np.unique(a, return_counts=True)

输出:

(array([1, 2, 3, 4, 5]), array([4, 4, 2, 1, 2], dtype=int64))

第一个数组是值,第二个数组是具有这些值的元素数。

因此,如果您只想获取包含数字的数组,则应使用以下代码:

np.unique(a, return_counts=True)[1]

8
from collections import Counter
a=["E","D","C","G","B","A","B","F","D","D","C","A","G","A","C","B","F","C","B"]

counter=Counter(a)

kk=[list(counter.keys()),list(counter.values())]

pd.DataFrame(np.array(kk).T, columns=['Letter','Count'])

尽管此代码段可能是解决方案,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而那些人可能不知道您提出代码建议的原因
Rahul Gupta

是的,Rahul Gupta
Anirban Lahiri

7
seta = set(a)
b = [a.count(el) for el in seta]
a = list(seta) #Only if you really want it.

4
count在这种情况下,使用列表非常昂贵并且是不必要的。
伊丹·K

@IdanK为什么计数很贵?
Kritika Rajain '18

@KritikaRajain对于列表中的每个唯一元素,您将遍历整个列表以生成一个计数(列表中唯一元素的数量为平方)。取而代之的是,您可以遍历列表一次,并计算每个唯一元素的数量(列表大小线性)。如果列表仅包含一个唯一元素,则结果将相同。而且,这种方法需要附加的中间集。
DylanYoung


4

对于第一个问题,请遍历列表并使用字典来跟踪元素的存在。

对于第二个问题,只需使用set运算符。


4
您能详细说明第一个答案吗?
布鲁斯(Bruce)2010年

3

这个答案更明确

a = [1,1,1,1,2,2,2,2,3,3,3,4,4]

d = {}
for item in a:
    if item in d:
        d[item] = d.get(item)+1
    else:
        d[item] = 1

for k,v in d.items():
    print(str(k)+':'+str(v))

# output
#1:4
#2:4
#3:3
#4:2

#remove dups
d = set(a)
print(d)
#{1, 2, 3, 4}

3
def frequencyDistribution(data):
    return {i: data.count(i) for i in data}   

print frequencyDistribution([1,2,3,4])

...

 {1: 1, 2: 1, 3: 1, 4: 1}   # originalNumber: count

3

我来晚了,但是这也可以,并且会帮助其他人:

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
freq_list = []
a_l = list(set(a))

for x in a_l:
    freq_list.append(a.count(x))


print 'Freq',freq_list
print 'number',a_l

会产生这个

Freq  [4, 4, 2, 1, 2]
number[1, 2, 3, 4, 5]

2
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

# 1. Get counts and store in another list
output = []
for i in set(a):
    output.append(a.count(i))
print(output)

# 2. Remove duplicates using set constructor
a = list(set(a))
print(a)
  1. Set集合不允许重复,将列表传递给set()构造函数将提供完全唯一的对象的可迭代项。传递列表中的对象时,count()函数返回整数计数。这样,对唯一对象进行计数,并通过将其附加到空列表输出中来存储每个计数值
  2. list()构造函数用于将set(a)转换为list并由相同的变量a引用

输出量

D:\MLrec\venv\Scripts\python.exe D:/MLrec/listgroup.py
[4, 4, 2, 1, 2]
[1, 2, 3, 4, 5]

2

使用字典的简单解决方案。

def frequency(l):
     d = {}
     for i in l:
        if i in d.keys():
           d[i] += 1
        else:
           d[i] = 1

     for k, v in d.iteritems():
        if v ==max (d.values()):
           return k,d.keys()

print(frequency([10,10,10,10,20,20,20,20,40,40,50,50,30]))

max(d.values())在最后一个循环中不会改变。不要在循环中计算它,而要在循环之前计算它。
DylanYoung

1
#!usr/bin/python
def frq(words):
    freq = {}
    for w in words:
            if w in freq:
                    freq[w] = freq.get(w)+1
            else:
                    freq[w] =1
    return freq

fp = open("poem","r")
list = fp.read()
fp.close()
input = list.split()
print input
d = frq(input)
print "frequency of input\n: "
print d
fp1 = open("output.txt","w+")
for k,v in d.items():
fp1.write(str(k)+':'+str(v)+"\n")
fp1.close()

1
num=[3,2,3,5,5,3,7,6,4,6,7,2]
print ('\nelements are:\t',num)
count_dict={}
for elements in num:
    count_dict[elements]=num.count(elements)
print ('\nfrequency:\t',count_dict)

2
请不要发布仅代码的答案,而要澄清您的代码,尤其是当问题已经有有效答案时。
艾瑞克(Erik)

1
from collections import OrderedDict
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
def get_count(lists):
    dictionary = OrderedDict()
    for val in lists:
        dictionary.setdefault(val,[]).append(1)
    return [sum(val) for val in dictionary.values()]
print(get_count(a))
>>>[4, 4, 2, 1, 2]

要删除重复项并维护订单:

list(dict.fromkeys(get_count(a)))
>>>[4, 2, 1]

1

我正在使用Counter生成频率。1行代码中来自文本文件单词的dict

def _fileIndex(fh):
''' create a dict using Counter of a
flat list of words (re.findall(re.compile(r"[a-zA-Z]+"), lines)) in (lines in file->for lines in fh)
'''
return Counter(
    [wrd.lower() for wrdList in
     [words for words in
      [re.findall(re.compile(r'[a-zA-Z]+'), lines) for lines in fh]]
     for wrd in wrdList])


0

在不使用集合的情况下使用另一种算法的另一种解决方案:

def countFreq(A):
   n=len(A)
   count=[0]*n                     # Create a new list initialized with '0'
   for i in range(n):
      count[A[i]]+= 1              # increase occurrence for value A[i]
   return [x for x in count if x]  # return non-zero count

0

您可以使用python中提供的内置函数

l.count(l[i])


  d=[]
  for i in range(len(l)):
        if l[i] not in d:
             d.append(l[i])
             print(l.count(l[i])

上面的代码自动删除列表中的重复项,并打印原始列表中每个元素的频率以及没有重复项的列表。

两只鸟一杆!XD


0

如果您不想使用任何库并使它简单明了,则可以尝试这种方法!

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
marked = []
b = [(a.count(i), marked.append(i))[0] for i in a if i not in marked]
print(b)

o / p

[4, 4, 2, 1, 2]

0

记录下来,一个功能性的答案:

>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]

如果您也算零,那会更干净:

>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]

一个解释:

  • 我们从一个空acc列表开始;
  • 如果下一个元素eL比规模下acc,我们只需更新这个元素:v+(i==e)手段v+1如果索引iacc是当前元素e,否则,前值v ;
  • 如果下一个元素eL大于或等于的大小acc,我们必须扩大acc,以容纳新的1

元素不必排序(itertools.groupby)。如果数字为负,则会得到怪异的结果。


0

找到了另一种使用集合的方法。

#ar is the list of elements
#convert ar to set to get unique elements
sock_set = set(ar)

#create dictionary of frequency of socks
sock_dict = {}

for sock in sock_set:
    sock_dict[sock] = ar.count(sock)

0

在列表中查找唯一元素

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
a = list(set(a))

使用字典查找排序数组中唯一元素的数量

def CountFrequency(my_list): 
# Creating an empty dictionary  
freq = {} 
for item in my_list: 
    if (item in freq): 
        freq[item] += 1
    else: 
        freq[item] = 1

for key, value in freq.items(): 
    print ("% d : % d"%(key, value))

# Driver function 
if __name__ == "__main__":  
my_list =[1, 1, 1, 5, 5, 3, 1, 3, 3, 1, 4, 4, 4, 2, 2, 2, 2] 

CountFrequency(my_list)

参考 GeeksforGeeks


-1

另一种方法是在天真的方法下面使用字典和list.count。

dicio = dict()

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

b = list()

c = list()

for i in a:

   if i in dicio: continue 

   else:

      dicio[i] = a.count(i)

      b.append(a.count(i))

      c.append(i)

print (b)

print (c)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.