Làm thế nào để đếm tần số của các yếu tố trong một danh sách không có thứ tự?


237

Tôi cần tìm tần số của các phần tử trong danh sách không có thứ tự

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

đầu ra->

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

Ngoài ra tôi muốn loại bỏ các bản sao từ một

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

Có phải họ luôn được ra lệnh như trong ví dụ đó?
Farinha

@Peter. Có, bạn đã sắp xếp danh sách cho các mục đích đăng. Danh sách sẽ luôn được sắp xếp?
S.Lott

2
Không, danh sách sẽ không được sắp xếp luôn. Đây không phải là bài tập về nhà.
Bruce

Tôi đang cố gắng vẽ đồ thị phân phối độ của một mạng.
Bruce

5
@Peter: Vui lòng cập nhật câu hỏi của bạn với thông tin hữu ích. Vui lòng không thêm nhận xét vào câu hỏi của bạn - bạn sở hữu câu hỏi, bạn có thể sửa nó để hoàn chỉnh và rõ ràng.
S.Lott

Câu trả lời:


147

Lưu ý: Bạn nên sắp xếp danh sách trước khi sử dụng groupby.

Bạn có thể sử dụng groupbytừ itertoolsgói nếu danh sách là một danh sách theo thứ tự.

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)]

Đầu ra:

[4, 4, 2, 1, 2]

tốt đẹp, sử dụng groupby. Tuy nhiên, tôi tự hỏi về hiệu quả của nó so với cách tiếp cận chính tả
Eli Bendersky

32
Nhóm python tạo ra các nhóm mới khi giá trị mà nó nhìn thấy thay đổi. Trong trường hợp này, 1,1,1,2,1,1,1] sẽ trả về [3,1,3]. Nếu bạn mong đợi [6,1] thì chỉ cần đảm bảo sắp xếp dữ liệu trước khi sử dụng nhóm.
Evan

4
@CristianCiupitu : sum(1 for _ in group).
Martijn Pieters

6
Đây không phải là một giải pháp. Đầu ra không cho biết những gì đã được tính.
buhtz

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

532

Trong Python 2.7 (hoặc mới hơn), bạn có thể sử dụng 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)]

Nếu bạn đang sử dụng Python 2.6 trở lên, bạn có thể tải xuống tại đây .


1
@unutbu: Nếu tôi có ba danh sách, a, b, c mà a và b vẫn giữ nguyên, nhưng c thay đổi thì sao? Làm thế nào để đếm giá trị của c mà a và c giống nhau?
ThePredator

@Srivatsan: Tôi không hiểu tình hình. Xin vui lòng gửi một câu hỏi mới, nơi bạn có thể giải thích.
unutbu

1
Có cách nào để trích xuất từ ​​điển {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} từ đối tượng truy cập không?
Pavan

7
@Pavan: collections.Counterlà một lớp con của dict. Bạn có thể sử dụng nó giống như cách bạn làm một lệnh chính quy bình thường. Tuy nhiên, nếu bạn thực sự muốn một dict, bạn có thể chuyển đổi nó thành một dict bằng cách sử dụng dict(counter).
unutbu

1
Cũng hoạt động trong 3.6, vì vậy, giả sử mọi thứ lớn hơn 2,7
kpierce8

108

Python 2.7+ giới thiệu Từ điển hiểu. Xây dựng từ điển từ danh sách sẽ giúp bạn đếm được cũng như thoát khỏi các bản sao.

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

Điều này hoạt động thực sự tốt với danh sách các chuỗi trái ngược với số nguyên như câu hỏi ban đầu được hỏi.
Glen Selle

15
Nó nhanh hơn khi sử dụng một bộ:{x:a.count(x) for x in set(a)}
stenci 17/2/2016

45
Điều này là không hiệu quả . a.count()thực hiện một giao dịch đầy đủ cho từng phần tử a, làm cho cách tiếp cận tứ giác O (N ^ 2) này. collections.Counter()hiệu quả hơn vì nó đếm trong thời gian tuyến tính (O (N)). Về số lượng, điều đó có nghĩa là cách tiếp cận này sẽ thực hiện 1 triệu bước cho danh sách có độ dài 1000, so với chỉ 1000 bước với Counter(), 10 ^ 12 bước trong đó Counter chỉ cần 10 ^ 6 cho một triệu mục trong danh sách, v.v.
Martijn Pieters

3
@stenci: chắc chắn, nhưng nỗi kinh hoàng của việc sử dụng a.count()hoàn toàn lùn hiệu quả của việc sử dụng một bộ ở đó.
Martijn Pieters

2
@MartijnPieters thêm một lý do để sử dụng nó ít lần hơn :)
stenci

48

Để đếm số lần xuất hiện:

from collections import defaultdict

appearances = defaultdict(int)

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

Để loại bỏ trùng lặp:

a = set(a) 

1
+1 cho bộ sưu tập.defaultdict. Ngoài ra, trong python 3.x, hãy tìm các bộ sưu tập. Nó giống như bộ sưu tập.defaultdict (int).
hughdbrown

2
@hughdbrown, thực sự Countercó thể sử dụng nhiều loại số bao gồm floathoặc Decimal, không chỉ int.
Cristian Ciupitu

28

Trong Python 2.7+, bạn có thể sử dụng các bộ sưu tập. Bộ đếm để đếm các mục

>>> 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
Bộ đếm chậm hơn nhiều so với dict mặc định và dict mặc định chậm hơn nhiều so với sử dụng dict thủ công.
Jonathan Ray

@JonathanRay, không còn nữa, stackoverflow.com/a/27802189/1382487 .
wsaleem

25

Đếm tần số của các yếu tố có lẽ được thực hiện tốt nhất với một từ điển:

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

Để loại bỏ các bản sao, sử dụng một bộ:

a = list(set(a))

3
@phkahler: Của tôi sẽ chỉ tốt hơn một chút so với điều này. Thật khó để tôi đăng một câu trả lời riêng biệt khi điều này có thể được cải thiện với một thay đổi nhỏ. Quan điểm của SO là đi đến câu trả lời tốt nhất . Tôi chỉ có thể chỉnh sửa điều này, nhưng tôi thích cho phép tác giả ban đầu có cơ hội thực hiện những cải tiến của riêng họ.
S.Lott

1
@ S.Lott Mã sạch hơn nhiều mà không phải nhập defaultdict.
bstrauch24

Tại sao không preinitialize b : b = {k:0 for k in a}?
DylanYoung

20

Đây là một thay thế succint khác sử dụng itertools.groupbycũng hoạt động cho đầu vào không có thứ tự:

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

các kết quả

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

16

Bạn có thể làm được việc này:

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

Đầu ra:

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

Mảng đầu tiên là các giá trị và mảng thứ hai là số phần tử có các giá trị này.

Vì vậy, nếu bạn muốn chỉ lấy mảng với các số bạn nên sử dụng:

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'])

Mặc dù đoạn mã này có thể là giải pháp, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn sẽ trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn
Rahul Gupta

Có sẽ làm điều đó 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
việc sử dụng danh sách countlà vô cùng tốn kém và chưa được áp dụng trong kịch bản này.
Idan K

@IdanK tại sao tính là đắt?
Kritika Rajain

@KritikaRajain Với mỗi phần tử duy nhất trong danh sách, bạn lặp lại toàn bộ danh sách để tạo số đếm (bậc hai trong số phần tử duy nhất trong danh sách). Thay vào đó, bạn có thể lặp lại danh sách một lần và đếm số lượng của từng yếu tố duy nhất (tuyến tính theo kích thước của danh sách). Nếu danh sách của bạn chỉ có một yếu tố duy nhất, kết quả sẽ giống nhau. Hơn nữa, phương pháp này đòi hỏi một bộ trung gian bổ sung.
DylanYoung


4

Đối với câu hỏi đầu tiên của bạn, lặp lại danh sách và sử dụng từ điển để theo dõi sự tồn tại của các yếu tố.

Đối với câu hỏi thứ hai của bạn, chỉ cần sử dụng toán tử thiết lập.


4
Bạn có thể giải thích về câu trả lời đầu tiên không
Bruce

3

Câu trả lời này rõ ràng hơn

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

Tôi đến khá muộn, nhưng điều này cũng sẽ hiệu quả và sẽ giúp đỡ người khác:

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

sẽ sản xuất cái này ..

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. Tập hợp tập hợp không cho phép trùng lặp, việc chuyển danh sách đến hàm tạo set () sẽ cung cấp một lần lặp các đối tượng hoàn toàn độc đáo. Hàm Count () trả về số nguyên khi một đối tượng trong danh sách được truyền. Với các đối tượng duy nhất được tính và mỗi giá trị đếm được lưu trữ bằng cách nối thêm vào một đầu ra danh sách trống
  2. hàm tạo list () được sử dụng để chuyển tập hợp (a) thành danh sách và được tham chiếu bởi cùng một biến a

Đầu ra

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

2

Giải pháp đơn giản sử dụng từ điển.

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())sẽ không thay đổi trong vòng lặp cuối cùng. Đừng tính toán nó trong vòng lặp, tính toán nó trước vòng lặp.
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
Vui lòng không đăng câu trả lời chỉ mã nhưng làm rõ mã của bạn, đặc biệt khi câu hỏi đã có câu trả lời hợp lệ.
Erik A

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]

Để loại bỏ trùng lặp và Duy trì trật tự:

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

1

Tôi đang sử dụng Counter để tạo freq. đọc từ từ tệp văn bản trong 1 dòng mã

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])

1

Một cách tiếp cận khác để làm điều này, mặc dù bằng cách sử dụng một thư viện nặng hơn nhưng mạnh mẽ - NLTK.

import nltk

fdist = nltk.FreqDist(a)
fdist.values()
fdist.most_common()

0

Một giải pháp khác với thuật toán khác mà không sử dụng các bộ sưu tập:

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

Bạn có thể sử dụng hàm dựng sẵn được cung cấp trong 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])

Đoạn mã trên tự động loại bỏ các bản sao trong danh sách và cũng in tần số của từng phần tử trong danh sách gốc và danh sách mà không trùng lặp.

Hai con chim cho một lần bắn! XD


0

Cách tiếp cận này có thể được thử nếu bạn không muốn sử dụng bất kỳ thư viện nào và giữ cho nó đơn giản và ngắn gọn!

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

Đối với hồ sơ, một câu trả lời chức năng:

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

Sẽ sạch hơn nếu bạn cũng đếm số không:

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

Một lời giải thích:

  • chúng tôi bắt đầu với một accdanh sách trống ;
  • nếu phần tử tiếp theo ecủa Lthấp hơn kích thước của acc, chúng ta chỉ cập nhật phần tử này: v+(i==e)có nghĩa là v+1nếu chỉ mục icủa acclà phần tử hiện tại e, nếu không thì giá trị trước đó v;
  • nếu phần tử tiếp theo ecủa Llà lớn hơn hoặc bằng với kích thước của acc, chúng ta phải mở rộng accđể lưu trữ mới 1.

Các phần tử không phải được sắp xếp ( itertools.groupby). Bạn sẽ nhận được kết quả kỳ lạ nếu bạn có số âm.


0

Tìm thấy một cách khác để làm điều này, sử dụng bộ.

#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

Để tìm các yếu tố độc đáo trong danh sách

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

Để tìm số lượng phần tử duy nhất trong một mảng được sắp xếp bằng từ điển

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)

Tham khảo GeekforGeek


-1

Một cách nữa là sử dụng từ điển và list.count, bên dưới một cách ngây thơ để làm điều đó.

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)

-1
a=[1,2,3,4,5,1,2,3]
b=[0,0,0,0,0,0,0]
for i in range(0,len(a)):
    b[a[i]]+=1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.