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]
Bruce
sumber
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]
Nadia Alramli
sumber
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 .

unutbu
sumber
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]
Amjith
sumber
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) 
Idan K
sumber
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]
KAMU
sumber
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))
bagian belakang
sumber
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}
rbento
sumber
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]
Evgenii Pavlov
sumber
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'])
Anirban Lahiri
sumber
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.
Lakshman Prasad
sumber
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.

t3rse
sumber
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}
Corey Richey
sumber
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
pengguna2422819
sumber
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]
Jax
sumber
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]
Sai Kiran
sumber
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]))
oshaiken
sumber
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()
amrutha
sumber
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)
chandan anand
sumber
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]
Pradam
sumber
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])
roberto
sumber
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()
Abhishek Poojary
sumber
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
Reza Abtin
sumber
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

Varun Shaandhesh
sumber
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]
Namrata Tolani
sumber
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.

jferard
sumber
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)
Abhishek Poojary
sumber
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

Gaurav Bansal
sumber
-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)
Valquiria F. Pereira
sumber
-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
AMITH MS
sumber