Jak policzyć częstotliwość elementów na liście nieuporządkowanej?


237

Muszę znaleźć częstotliwość elementów na nieuporządkowanej liście

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

wyjście->

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

Również chcę usunąć duplikaty z

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

Czy zawsze są zamawiane jak w tym przykładzie?
Farinha

@Piotr. Tak, posortowałeś listę do celów opublikowania. Czy lista będzie zawsze sortowana?
S.Lott,

2
Nie, lista nie zawsze będzie sortowana. To nie jest praca domowa.
Bruce

Próbuję wykreślić wykres rozkładu stopni w sieci.
Bruce

5
@Peter: Zaktualizuj swoje pytanie przydatnymi informacjami. Nie dodawaj komentarzy do pytania - jesteś właścicielem pytania, możesz je naprawić, aby było kompletne i jasne.
S.Lott

Odpowiedzi:


147

Uwaga: Przed użyciem należy posortować listę groupby.

Możesz użyć groupbyz itertoolspakietu, jeśli lista jest listą uporządkowaną.

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

Wynik:

[4, 4, 2, 1, 2]

miło, używając groupby. Zastanawiam się jednak nad jego efektywnością w porównaniu z podejściem dyktatorskim
Eli Bendersky

32
Python groupby tworzy nowe grupy, gdy zmieni się wartość, którą widzi. W tym przypadku 1,1,1,2,1,1,1] zwróci [3,1,3]. Jeśli spodziewałeś się [6,1], po prostu posortuj dane przed użyciem groupby.
Evan

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

6
To nie jest rozwiązanie. Dane wyjściowe nie mówią, co zostało policzone.
buhtz

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

532

W Pythonie 2.7 (lub nowszym) możesz użyć 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)]

Jeśli używasz języka Python 2.6 lub starszego, możesz go pobrać tutaj .


1
@unutbu: Co jeśli mam trzy listy, a, b, c, dla których aib pozostają takie same, ale zmienia się c? Jak policzyć wartość c, dla której a i c są takie same?
ThePredator

@Srivatsan: Nie rozumiem sytuacji. Proszę zamieścić nowe pytanie, w którym można opracować.
unutbu

1
Czy istnieje sposób na wyodrębnienie słownika {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} z obiektu licznika?
Pavan

7
@Pavan: collections.Counterjest podklasą dict. Możesz go używać w taki sam sposób, jak normalny dyktand. Jeśli jednak naprawdę chcesz dykta, możesz go przekonwertować na dykt za pomocą dict(counter).
unutbu

1
Działa również w wersji 3.6, więc załóżmy, że jest większa niż 2,7
kpierce8,

108

Python 2.7+ wprowadza rozumienie słownika. Zbudowanie słownika z listy pozwoli ci liczyć, a także pozbyć się duplikatów.

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

Działa to naprawdę dobrze z listami ciągów w przeciwieństwie do liczb całkowitych, takich jak pierwotne pytanie.
Glen Selle,

15
Jest to szybsze przy użyciu zestawu:{x:a.count(x) for x in set(a)}
stenci

45
Jest to bardzo nieefektywne . a.count()wykonuje pełny trawers dla każdego elementu a, czyniąc z tego podejście kwadratowe O (N ^ 2). collections.Counter()jest znacznie bardziej wydajny, ponieważ liczy się w czasie liniowym (O (N)). Liczbowo oznacza to, że to podejście wykona 1 milion kroków dla listy o długości 1000, w porównaniu do zaledwie 1000 kroków z Counter(), 10 ^ 12 kroków, w których Counter potrzebuje tylko 10 ^ 6 dla miliona pozycji na liście itp.
Martijn Pieters

3
@stenci: jasne, ale horror używania a.count()całkowicie przyćmiewa skuteczność korzystania z zestawu.
Martijn Pieters

2
@MartijnPieters jeszcze jeden powód, aby używać go mniej razy :)
stenci

48

Aby policzyć liczbę wystąpień:

from collections import defaultdict

appearances = defaultdict(int)

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

Aby usunąć duplikaty:

a = set(a) 

1
+1 za kolekcje.defaultdict. Ponadto w Pythonie 3.x wyszukaj kolekcje.Counter. Jest to to samo, co collections.defaultdict (int).
hughdbrown

2
@hughdbrown, faktycznie Countermoże używać wielu typów numerycznych, w tym floatlub Decimalnie tylko int.
Cristian Ciupitu

28

W Pythonie 2.7+ możesz używać kolekcji. Licznik do liczenia elementów

>>> 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
Licznik jest znacznie wolniejszy niż domyślny, a domyślny jest znacznie wolniejszy niż ręczne użycie.
Jonathan Ray

@JathanathanRay, już nie, stackoverflow.com/a/27802189/1382487 .
wsaleem,

25

Prawdopodobnie najlepiej policzyć częstotliwość elementów za pomocą słownika:

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

Aby usunąć duplikaty, użyj zestawu:

a = list(set(a))

3
@phkahler: Mój byłby tylko trochę lepszy od tego. Nie warto dodawać osobnej odpowiedzi, gdy można ją poprawić za pomocą niewielkiej zmiany. Celem SO jest uzyskanie najlepszych odpowiedzi. Mógłbym to po prostu edytować, ale wolę pozwolić oryginalnemu autorowi na wprowadzenie własnych ulepszeń.
S.Lott,

1
@ S.Lott Kod jest znacznie czystszy bez konieczności importowania defaultdict.
bstrauch24,

Dlaczego nie preinitialize b: b = {k:0 for k in a}?
DylanYoung

20

Oto kolejna korzystna alternatywa, itertools.groupbyktóra działa również w przypadku nieuporządkowanych danych wejściowych:

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

wyniki

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

16

Możesz to zrobić:

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

Wynik:

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

Pierwsza tablica to wartości, a druga tablica to liczba elementów o tych wartościach.

Więc jeśli chcesz uzyskać tylko tablicę z liczbami, powinieneś użyć tego:

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

Ten fragment kodu może być rozwiązaniem, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, a ci ludzie mogą nie znać powodów Twojej sugestii kodu
Rahul Gupta

Tak zrobi to 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
korzystanie z list countjest absurdalnie drogie i nieuzasadnione w tym scenariuszu.
Idan K

@IdanK dlaczego liczenie jest drogie?
Kritika Rajain

@KritikaRajain Dla każdego unikalnego elementu na liście iterujesz całą listę, aby wygenerować liczbę (kwadratową liczbę unikalnych elementów na liście). Zamiast tego możesz iterować listę raz i policzyć liczbę każdego unikalnego elementu (liniowo w stosunku do listy). Jeśli lista zawiera tylko jeden unikalny element, wynik będzie taki sam. Ponadto takie podejście wymaga dodatkowego zestawu pośredniego.
DylanYoung


4

W przypadku pierwszego pytania powtórz listę i użyj słownika, aby śledzić istnienie elementów.

Do drugiego pytania wystarczy użyć operatora ustawiania.


4
Czy możesz rozwinąć pierwszą odpowiedź
Bruce

3

Ta odpowiedź jest bardziej jednoznaczna

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

Jestem spóźniony, ale to również zadziała i pomoże innym:

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

wyprodukuje to ..

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. Kolekcja zestawów nie pozwala na duplikaty, przekazanie listy do konstruktora set () da iterowalność całkowicie unikatowych obiektów. Funkcja count () zwraca liczbę całkowitą po przekazaniu obiektu znajdującego się na liście. Dzięki temu zliczane są unikalne obiekty, a każda wartość zliczania jest zapisywana przez dołączenie do pustej listy wyników
  2. Konstruktor list () służy do konwersji zestawu (a) na listę i odwołuje się do niego ta sama zmienna a

Wynik

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

2

Proste rozwiązanie za pomocą słownika.

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())nie zmieni się w ostatniej pętli. Nie obliczaj go w pętli, oblicz go przed pętlą.
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
Nie publikuj odpowiedzi tylko na kod, ale wyjaśnij swój kod, zwłaszcza jeśli pytanie ma już prawidłową odpowiedź.
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]

Aby usunąć duplikaty i utrzymać porządek:

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

1

Używam licznika do generowania częstotliwości. dyktuj ze słów w pliku tekstowym w 1 linii kodu

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

Inne podejście do tego celu, aczkolwiek przy użyciu cięższej, ale potężnej biblioteki - NLTK.

import nltk

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

0

Jeszcze inne rozwiązanie z innym algorytmem bez użycia kolekcji:

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

Możesz użyć wbudowanej funkcji dostarczonej w Pythonie

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

Powyższy kod automatycznie usuwa duplikaty z listy, a także drukuje częstotliwość każdego elementu na oryginalnej liście i liście bez duplikatów.

Dwa ptaki za jeden strzał! XD


0

To podejście można wypróbować, jeśli nie chcesz korzystać z żadnej biblioteki i jest ona prosta i krótka!

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

Dla przypomnienia, funkcjonalna odpowiedź:

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

Jest czystszy, jeśli zliczasz również zera:

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

Wyjaśnienie:

  • zaczynamy od pustej acclisty;
  • jeśli kolejny element ez Ljest mniejsza niż rozmiar acc, po prostu zaktualizować ten element: v+(i==e)środki v+1, jeśli indeks iz accjest obecny pierwiastek e, inaczej poprzednia wartość v;
  • jeśli kolejny element eod Ljest większa lub równa wielkości acc, musimy poszerzyć accgospodarzem nowego 1.

Elementy nie muszą być sortowane ( itertools.groupby). Otrzymasz dziwne wyniki, jeśli masz liczby ujemne.


0

Znalazłem inny sposób na to, używając zestawów.

#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

Aby znaleźć unikalne elementy na liście

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

Aby znaleźć liczbę unikalnych elementów w posortowanej tablicy za pomocą słownika

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)

Odniesienie GeeksforGeeks


-1

Jeszcze jednym sposobem jest użycie słownika i list.count, poniżej naiwnego sposobu na zrobienie tego.

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.