@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)]
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
@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
@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))}
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.
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
7
Chciałbym po prostu użyć scipy.stats.itemfreq w następujący sposób:
from scipy.stats import itemfreq
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]
freq = itemfreq(a)
a = freq[:,0]
b = freq[:,1]
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)+1else:
d[item]=1for 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}
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)
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
Konstruktor list () służy do konwersji zestawu (a) na listę i odwołuje się do niego ta sama zmienna a
def frequency(l):
d ={}for i in l:if i in d.keys():
d[i]+=1else:
d[i]=1for 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/pythondef frq(words):
freq ={}for w in words:if w in freq:
freq[w]= freq.get(w)+1else:
freq[w]=1return 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()
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)
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 importOrderedDict
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]
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)
'''returnCounter([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])
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
>>> 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+[0for _ 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+[0for _ 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.
#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)
Aby znaleźć liczbę unikalnych elementów w posortowanej tablicy za pomocą słownika
defCountFrequency(my_list):# Creating an empty dictionary
freq ={}for item in my_list:if(item in freq):
freq[item]+=1else:
freq[item]=1for 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)
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:continueelse:
dicio[i]= a.count(i)
b.append(a.count(i))
c.append(i)print(b)print(c)
Odpowiedzi:
Uwaga: Przed użyciem należy posortować listę
groupby
.Możesz użyć
groupby
zitertools
pakietu, jeśli lista jest listą uporządkowaną.Wynik:
źródło
groupby
. Zastanawiam się jednak nad jego efektywnością w porównaniu z podejściem dyktatorskimsum(1 for _ in group)
.[(key, len(list(group))) for key, group in groupby(a)]
lub{key: len(list(group)) for key, group in groupby(a)}
@buhtzW Pythonie 2.7 (lub nowszym) możesz użyć
collections.Counter
:Jeśli używasz języka Python 2.6 lub starszego, możesz go pobrać tutaj .
źródło
collections.Counter
jest 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)
.Python 2.7+ wprowadza rozumienie słownika. Zbudowanie słownika z listy pozwoli ci liczyć, a także pozbyć się duplikatów.
źródło
{x:a.count(x) for x in set(a)}
a.count()
wykonuje pełny trawers dla każdego elementua
, 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 zCounter()
, 10 ^ 12 kroków, w których Counter potrzebuje tylko 10 ^ 6 dla miliona pozycji na liście itp.a.count()
całkowicie przyćmiewa skuteczność korzystania z zestawu.Aby policzyć liczbę wystąpień:
Aby usunąć duplikaty:
źródło
Counter
może używać wielu typów numerycznych, w tymfloat
lubDecimal
nie tylkoint
.W Pythonie 2.7+ możesz używać kolekcji. Licznik do liczenia elementów
źródło
Prawdopodobnie najlepiej policzyć częstotliwość elementów za pomocą słownika:
Aby usunąć duplikaty, użyj zestawu:
źródło
defaultdict
.b = {k:0 for k in a}
?Oto kolejna korzystna alternatywa,
itertools.groupby
która działa również w przypadku nieuporządkowanych danych wejściowych:wyniki
źródło
Możesz to zrobić:
Wynik:
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:
źródło
źródło
źródło
count
jest absurdalnie drogie i nieuzasadnione w tym scenariuszu.Chciałbym po prostu użyć scipy.stats.itemfreq w następujący sposób:
możesz sprawdzić dokumentację tutaj: http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.stats.itemfreq.html
źródło
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.
źródło
Ta odpowiedź jest bardziej jednoznaczna
źródło
...
źródło
Jestem spóźniony, ale to również zadziała i pomoże innym:
wyprodukuje to ..
źródło
Wynik
źródło
Proste rozwiązanie za pomocą słownika.
źródło
max(d.values())
nie zmieni się w ostatniej pętli. Nie obliczaj go w pętli, oblicz go przed pętlą.źródło
źródło
Aby usunąć duplikaty i utrzymać porządek:
źródło
Używam licznika do generowania częstotliwości. dyktuj ze słów w pliku tekstowym w 1 linii kodu
źródło
Inne podejście do tego celu, aczkolwiek przy użyciu cięższej, ale potężnej biblioteki - NLTK.
źródło
Jeszcze inne rozwiązanie z innym algorytmem bez użycia kolekcji:
źródło
Możesz użyć wbudowanej funkcji dostarczonej w Pythonie
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
źródło
To podejście można wypróbować, jeśli nie chcesz korzystać z żadnej biblioteki i jest ona prosta i krótka!
o / p
źródło
Dla przypomnienia, funkcjonalna odpowiedź:
Jest czystszy, jeśli zliczasz również zera:
Wyjaśnienie:
acc
listy;e
zL
jest mniejsza niż rozmiaracc
, po prostu zaktualizować ten element:v+(i==e)
środkiv+1
, jeśli indeksi
zacc
jest obecny pierwiasteke
, inaczej poprzednia wartośćv
;e
odL
jest większa lub równa wielkościacc
, musimy poszerzyćacc
gospodarzem nowego1
.Elementy nie muszą być sortowane (
itertools.groupby
). Otrzymasz dziwne wyniki, jeśli masz liczby ujemne.źródło
Znalazłem inny sposób na to, używając zestawów.
źródło
źródło
Jeszcze jednym sposobem jest użycie słownika i list.count, poniżej naiwnego sposobu na zrobienie tego.
źródło
źródło