Bagaimana cara menghitung frekuensi elemen dalam daftar yang tidak diurutkan?


237

Saya perlu menemukan frekuensi elemen dalam daftar tidak terurut

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

output->

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

Saya juga ingin menghapus duplikat dari

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

Apakah mereka selalu dipesan seperti dalam contoh itu?
Farinha

@ Peter. Ya, Anda sudah mengurutkan daftar untuk keperluan posting. Apakah daftar akan selalu disortir?
S.Lott

2
Tidak, daftar tidak akan selalu diurutkan. Ini bukan pekerjaan rumah.
Bruce

Saya mencoba untuk memetakan grafik distribusi derajat jaringan.
Bruce

5
@ Peter: Harap perbarui pertanyaan Anda dengan informasi yang bermanfaat. Tolong jangan menambahkan komentar ke pertanyaan Anda - Anda memiliki pertanyaan, Anda dapat memperbaikinya menjadi lengkap dan jelas.
S.Lott

Jawaban:


147

Catatan: Anda harus mengurutkan daftar sebelum menggunakan groupby.

Anda dapat menggunakan groupbydari itertoolspaket jika daftar adalah daftar yang diurutkan.

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

Keluaran:

[4, 4, 2, 1, 2]

bagus, menggunakan groupby. Saya bertanya-tanya tentang efisiensinya versus pendekatan dikt,
Eli Bendersky

32
Python groupby membuat grup baru ketika nilai yang dilihatnya berubah. Dalam hal ini 1,1,1,2,1,1,1] akan kembali [3,1,3]. Jika Anda berharap [6,1] maka pastikan untuk mengurutkan data sebelum menggunakan groupby.
Evan

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

6
Ini bukan solusi. Keluaran tidak memberi tahu apa yang dihitung.
buhtz

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

532

Di Python 2.7 (atau lebih baru), Anda dapat menggunakan 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)]

Jika Anda menggunakan Python 2.6 atau yang lebih lama, Anda dapat mengunduhnya di sini .


1
@unutbu: Bagaimana jika saya memiliki tiga daftar, a, b, c yang a dan b tetap sama, tetapi c berubah? Bagaimana cara menghitung nilai c dimana a dan c sama?
ThePredator

@Srivatsan: Saya tidak mengerti situasinya. Silakan kirim pertanyaan baru di mana Anda dapat menguraikan.
unutbu

1
Apakah ada cara untuk mengekstrak kamus {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} dari objek counter?
Pavan

7
@Pavan: collections.Counteradalah subkelas dari dict. Anda dapat menggunakannya dengan cara yang sama seperti yang Anda lakukan pada dict normal. Namun, jika Anda benar-benar menginginkan dikt, Anda dapat mengonversinya menjadi dikt menggunakan dict(counter).
unutbu

1
Berfungsi di 3.6 juga, jadi anggap sesuatu yang lebih besar dari 2,7
kpierce8

108

Python 2.7+ memperkenalkan Kamus Pemahaman. Membangun kamus dari daftar akan membuat Anda menghitung serta menyingkirkan duplikat.

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

Ini bekerja sangat baik dengan daftar string yang bertentangan dengan bilangan bulat seperti pertanyaan awal yang diajukan.
Glen Selle

15
Lebih cepat menggunakan satu set:{x:a.count(x) for x in set(a)}
stenci

45
Ini sangat tidak efisien . a.count()melakukan lintasan penuh untuk setiap elemen dalam a, menjadikan ini pendekatan O (N ^ 2) kuadratik. collections.Counter()adalah jauh lebih efisien karena penting dalam waktu linear (O (N)). Dalam angka, itu berarti pendekatan ini akan mengeksekusi 1 juta langkah untuk daftar panjang 1000, vs hanya 1000 langkah dengan Counter(), 10 ^ 12 langkah di mana hanya 10 ^ 6 dibutuhkan oleh Counter untuk sejuta item dalam daftar, dll.
Martijn Pieters

3
@stenci: tentu, tetapi kengerian menggunakan a.count()sepenuhnya kerdil efisiensi menggunakan set di sana.
Martijn Pieters

2
@ MartijnPieters satu lagi alasan untuk menggunakannya lebih sedikit kali :)
stenci

48

Untuk menghitung jumlah penampilan:

from collections import defaultdict

appearances = defaultdict(int)

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

Untuk menghapus duplikat:

a = set(a) 

1
+1 untuk collections.defaultdict. Juga, dalam python 3.x, cari collections.Counter. Itu sama dengan collections.defaultdict (int).
hughdbrown

2
@ hughdbrown, sebenarnya Counterbisa menggunakan beberapa tipe numerik termasuk floatatau Decimal, bukan hanya int.
Cristian Ciupitu

28

Dalam Python 2.7+, Anda bisa menggunakan collections.Counter untuk menghitung item

>>> 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
Penghitung jauh lebih lambat daripada dict default, dan dict default jauh lebih lambat daripada penggunaan manual dict.
Jonathan Ray

@ JonathanRay, tidak lagi, stackoverflow.com/a/27802189/1382487 .
wsaleem

25

Menghitung frekuensi elemen mungkin paling baik dilakukan dengan kamus:

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

Untuk menghapus duplikat, gunakan satu set:

a = list(set(a))

3
@phkahler: Milik saya hanya akan sedikit lebih baik dari ini. Sangat tidak layak saya memposting jawaban terpisah ketika ini dapat ditingkatkan dengan perubahan kecil. Tujuan SO adalah untuk mendapatkan jawaban terbaik . Saya cukup mengedit ini, tetapi saya lebih suka membiarkan penulis asli kesempatan untuk melakukan perbaikan sendiri.
S.Lott

1
@ S.Lott Kode jauh lebih bersih tanpa harus mengimpor defaultdict.
bstrauch24

Mengapa tidak preinitialize b: b = {k:0 for k in a}?
DylanYoung

20

Berikut ini adalah alternatif penggunaan succint lain itertools.groupbyyang juga berfungsi untuk input yang tidak terurut:

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

hasil

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

16

Kamu bisa melakukan ini:

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

Keluaran:

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

Array pertama adalah nilai, dan array kedua adalah jumlah elemen dengan nilai-nilai ini.

Jadi Jika Anda ingin mendapatkan hanya array dengan angka, Anda harus menggunakan ini:

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

Sementara cuplikan kode ini mungkin solusinya, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda
Rahul Gupta

Ya akan melakukannya 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
menggunakan daftar countsangat mahal dan tidak pantas untuk skenario ini.
Idan K

@IdanK mengapa menghitung itu mahal?
Kritika Rajain

@KritikaRajain Untuk setiap elemen unik dalam daftar, Anda mengulangi seluruh daftar untuk menghasilkan hitungan (kuadratik dalam jumlah elemen unik dalam daftar). Sebagai gantinya, Anda dapat mengulangi daftar sekali dan menghitung jumlah setiap elemen unik (linier dalam ukuran daftar). Jika daftar Anda hanya memiliki satu elemen unik, hasilnya akan sama. Selain itu, pendekatan ini membutuhkan set perantara tambahan.
DylanYoung


4

Untuk pertanyaan pertama Anda, ulangi daftar dan gunakan kamus untuk melacak keberadaan elemen.

Untuk pertanyaan kedua Anda, cukup gunakan operator yang telah ditentukan.


4
Bisakah Anda jelaskan jawaban pertama
Bruce

3

Jawaban ini lebih eksplisit

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

Saya agak terlambat, tetapi ini juga akan berhasil, dan akan membantu orang lain:

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

akan menghasilkan ini ..

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. Kumpulan koleksi tidak memungkinkan duplikat, meneruskan daftar ke konstruktor set () akan memberikan objek yang benar-benar unik. fungsi count () mengembalikan jumlah integer ketika objek yang ada dalam daftar diteruskan. Dengan itu objek unik dihitung dan masing-masing nilai hitungan disimpan dengan menambahkan ke output daftar kosong
  2. list () konstruktor digunakan untuk mengonversi set (a) menjadi daftar dan dirujuk oleh variabel yang sama a

Keluaran

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

2

Solusi sederhana menggunakan kamus.

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())tidak akan berubah di loop terakhir. Jangan hitung dalam loop, hitung sebelum loop.
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
Tolong jangan memposting jawaban hanya kode tetapi mengklarifikasi kode Anda, terutama ketika pertanyaan sudah memiliki jawaban yang valid.
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]

Untuk menghapus duplikat dan Menjaga pesanan:

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

1

Saya menggunakan Penghitung untuk menghasilkan freq. dikt dari kata-kata file teks dalam 1 baris kode

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

Pendekatan lain untuk melakukan ini, meskipun dengan menggunakan perpustakaan yang lebih berat tetapi kuat - NLTK.

import nltk

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

0

Solusi lain dengan algoritma lain tanpa menggunakan koleksi:

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

Anda dapat menggunakan fungsi built-in yang disediakan dengan 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])

Kode di atas secara otomatis menghapus duplikat dalam daftar dan juga mencetak frekuensi setiap elemen dalam daftar asli dan daftar tanpa duplikat.

Dua burung untuk satu tembakan! XD


0

Pendekatan ini dapat dicoba jika Anda tidak ingin menggunakan perpustakaan apa pun dan tetap sederhana dan singkat!

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 / h

[4, 4, 2, 1, 2]

0

Sebagai catatan, jawaban fungsional:

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

Lebih bersih jika Anda menghitung nol juga:

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

Sebuah penjelasan:

  • kita mulai dengan accdaftar kosong ;
  • jika elemen berikutnya edari Llebih rendah dari ukuran acc, kami hanya update elemen ini: v+(i==e)berarti v+1jika indeks idari accadalah elemen saat ini e, jika nilai sebelumnya v;
  • jika elemen berikutnya edari Llebih besar atau sama dengan ukuran acc, kami harus memperluas accuntuk menjadi tuan rumah baru 1.

Elemen tidak harus diurutkan ( itertools.groupby). Anda akan mendapatkan hasil yang aneh jika Anda memiliki angka negatif.


0

Menemukan cara lain untuk melakukan ini, menggunakan set.

#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

Untuk menemukan elemen unik dalam daftar

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

Untuk menemukan jumlah elemen unik dalam array yang diurutkan menggunakan kamus

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)

Referensi GeeksforGeeks


-1

Satu lagi cara adalah dengan menggunakan kamus dan list.count, di bawah ini cara naif untuk melakukannya.

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.