순서가없는 목록에서 요소의 빈도를 계산하는 방법은 무엇입니까?


237

순서없는 목록 에서 요소의 빈도를 찾아야 합니다.

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

출력->

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

또한 중복을 제거하고 싶습니다.

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

그들은 항상 그 예 에서처럼 주문됩니까?
Farinha

@베드로. 예, 게시 목적으로 목록을 정렬했습니다. 목록이 항상 정렬됩니까?
S.Lott

2
아니요, 목록이 항상 정렬되지는 않습니다. 이것은 숙제가 아닙니다.
Bruce

네트워크의 학위 분포 그래프를 그리려고합니다.
Bruce

5
@ 피터 : 유용한 정보로 질문을 업데이트하십시오. 질문에 의견을 추가하지 마십시오. 질문을 소유 한 경우 완전하고 명확하게 수정할 수 있습니다.
S.Lott

답변:


147

참고 :를 사용하기 전에 목록을 정렬해야합니다 groupby.

목록이 주문 목록 인 경우 패키지 groupby에서 사용할 수 있습니다 itertools.

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

산출:

[4, 4, 2, 1, 2]

사용하여 groupby좋습니다. 나는 불구하고, DICT 접근 대 효율성에 대해 궁금해
엘리 Bendersky

32
파이썬 그룹은 값이 변경되면 새 그룹을 만듭니다. 이 경우 1,1,1,2,1,1,1]은 [3,1,3]을 반환합니다. [6,1]을 예상했다면 groupby를 사용하기 전에 데이터를 정렬해야합니다.
Evan

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

6
이것은 해결책이 아닙니다. 출력은 계산 된 내용을 알려주지 않습니다.
buhtz

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

532

Python 2.7 이상에서는 다음을 사용할 수 있습니다 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)]

Python 2.6 이상을 사용하는 경우 여기에서 다운로드 할 수 있습니다 .


1
@ unutbu : a와 b가 동일하게 유지되는 c, a, b, c의 세 가지 목록이 있지만 c가 변경되면 어떻게됩니까? a와 c가 동일한 c의 값을 계산하는 방법은 무엇입니까?
ThePredator 2016 년

@Srivatsan : 상황을 이해하지 못합니다. 정교하게 할 수있는 새로운 질문을 게시하십시오.
unutbu 2016 년

1
카운터 객체에서 사전 {1 : 4, 2 : 4, 3 : 2, 5 : 2, 4 : 1}을 추출하는 방법이 있습니까?
Pavan

7
@Pavan : collections.Counter의 하위 클래스입니다 dict. 일반적인 방법과 같은 방식으로 사용할 수 있습니다. 그러나 실제로 dict을 원한다면을 사용하여 dict로 변환 할 수 dict(counter)있습니다.
unutbu

1
3.6의 작품은, 그래서 가정 아무것도 더 큰 2.7 이상
kpierce8

108

Python 2.7+에는 사전 이해력이 도입되었습니다. 목록에서 사전을 작성하면 중복을 제거하고 개수를 얻을 수 있습니다.

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

이것은 원래 질문과 같은 정수가 아닌 문자열 목록에서 실제로 잘 작동합니다.
Glen Selle

15
세트를 사용하는 것이 더 빠릅니다.{x:a.count(x) for x in set(a)}
stenci

45
이것은 매우 비효율적 입니다. a.count()않습니다 전체 트래버스 각 요소에 대해 를 수행 a하여 O (N ^ 2) 2 차 접근 방식으로 만듭니다. collections.Counter()훨씬 더 효율적 이 선형 시간 (O (N))에서 계산하기 때문이다. 즉,이 접근 방식은 길이가 1000 인 목록에 대해 백만 단계를 실행하고 Counter(), 10 ^ 12 단계를 가진 1000 단계 만 수행하고, 목록에 있는 백만 개의 항목에 대해 카운터가 10 ^ 6 만 필요한 10 ^ 6 단계 만 수행함을 의미합니다.
Martijn Pieters

3
@stenci : 물론입니다. 그러나 a.count()완전히 사용하는 것에 대한 공포는 거기에있는 세트를 사용하는 효율성을 떨어 뜨립니다 .
Martijn Pieters

2
@MartijnPieters 더 적은 시간을 사용해야하는 또 하나의 이유 :)
stenci

48

모양 수를 세려면

from collections import defaultdict

appearances = defaultdict(int)

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

중복을 제거하려면

a = set(a) 

1
컬렉션의 경우 +1입니다. 또한 python 3.x에서 collections.Counter를 찾으십시오. collections.defaultdict (int)와 동일합니다.
hughdbrown

2
@hughdbrown, 실제로 Counter여러 숫자 유형을 포함하여 사용할 수 있습니다 float또는 Decimal뿐만 아니라, int.
Cristian Ciupitu

28

Python 2.7 이상에서는 컬렉션 을 사용할 수 있습니다.

>>> 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
카운터는 기본 dict보다 훨씬 느리며 기본 dict는 dict를 수동으로 사용하는 것보다 훨씬 느립니다.
Jonathan Ray

더 이상 @JonathanRay는 stackoverflow.com/a/27802189/1382487 입니다.
wsaleem

25

요소의 빈도를 세는 것은 사전을 사용하여 수행하는 것이 가장 좋습니다.

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

중복을 제거하려면 세트를 사용하십시오.

a = list(set(a))

3
@ phkahler : 광산은 이것보다 조금 나을 것입니다. 작은 변화로 개선 될 수있을 때 별도의 답변을 게시하는 것은 가치가 없습니다. SO의 요점은 최상의 답변 을 얻는 것입니다. 나는 이것을 간단히 편집 할 수 있지만, 원저자에게 자신의 개선을 할 수있는 기회를 허용하는 것을 선호한다.
S.Lott

1
@ S.Lott 코드를 가져올 필요없이 훨씬 더 깨끗 defaultdict합니다.
bstrauch24

왜 b를 미리 초기화하지 b = {k:0 for k in a}않습니까?
DylanYoung

20

다음 itertools.groupby은 정렬되지 않은 입력에도 작동하는 또 다른 간결한 대안입니다 .

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

결과

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

16

당신은 이것을 할 수 있습니다 :

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

산출:

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

첫 번째 배열은 값이고 두 번째 배열은 이러한 값을 가진 요소의 수입니다.

따라서 숫자로만 배열하려면 다음을 사용해야합니다.

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

이 코드 스 니펫이 해결책이 될 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자들에게이 질문에 대한 답변을 제공하고 있으며 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다.
Rahul Gupta

네, 그렇게 할 것입니다 Rahul Gupta
안 어반 라히리

7
seta = set(a)
b = [a.count(el) for el in seta]
a = list(seta) #Only if you really want it.

4
count이 시나리오 에서는 목록을 사용하는 것이 엄청나게 비싸고 불필요합니다.
Idan K

@IdanK 왜 카운트가 비싼가요?
Kritika Rajain

@KritikaRajain 목록의 각 고유 요소에 대해 전체 목록을 반복하여 카운트를 생성합니다 (목록의 고유 요소 수에 이차). 대신 목록을 한 번 반복하고 각 고유 요소의 수를 계산합니다 (목록 크기의 선형). 목록에 고유 한 요소가 하나만 있으면 결과는 동일합니다. 또한이 방법에는 추가 중간 세트가 필요합니다.
DylanYoung


4

첫 번째 질문의 경우 목록을 반복하고 사전을 사용하여 요소 존재를 추적하십시오.

두 번째 질문은 set 연산자를 사용하십시오.


4
첫 번째 답변을 자세히 설명해 주시겠습니까
Bruce

3

이 답변은 더 명확합니다

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

나는 꽤 늦었지만 이것도 효과가 있으며 다른 사람들을 도울 것입니다.

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

이것을 생산할 것입니다 ..

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. Set 컬렉션은 중복을 허용하지 않고 set () 생성자에 목록을 전달하면 완전히 고유 한 객체를 반복 할 수 있습니다. count () 함수는 목록에있는 객체가 전달 될 때 정수 개수를 반환합니다. 이를 통해 고유 한 객체가 계산되고 각 카운트 값이 빈 목록 출력에 추가되어 저장됩니다.
  2. list () 생성자는 set (a)를 목록으로 변환하는 데 사용되며 동일한 변수 a로 참조됩니다.

산출

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

2

사전을 사용하는 간단한 솔루션.

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())마지막 루프에서 변경되지 않습니다. 루프에서 계산하지 말고 루프 전에 계산하십시오 .
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
코드 전용 답변을 게시하지 말고 특히 질문에 이미 유효한 답변이있는 경우 코드를 명확히하십시오.
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]

중복을 제거하고 순서를 유지하려면 :

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

1

카운터를 사용하여 주파수를 생성하고 있습니다. 한 줄의 코드로 텍스트 파일 단어에서 받아쓰기

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

더 강력하지만 강력한 라이브러리 인 NLTK를 사용하여이 작업을 수행하는 또 다른 방법입니다.

import nltk

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

0

컬렉션을 사용하지 않고 다른 알고리즘을 사용하는 또 다른 솔루션 :

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

파이썬에서 제공하는 내장 함수를 사용할 수 있습니다

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

위의 코드는 목록에서 중복을 자동으로 제거하고 원본 목록과 중복없이 목록의 각 요소 빈도를 인쇄합니다.

한 번에 두 마리의 새! XD


0

이 방법은 라이브러리를 사용하지 않고 간단하고 짧게 유지하려는 경우 시도 할 수 있습니다!

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

기록적인 기능적인 답변 :

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

0을 세면 더 깨끗합니다.

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

설명:

  • 우리는 빈 시작 acc 목록으로 합니다.
  • 다음 요소 경우 e의는 L의 크기보다 낮은 acc, 우리는 단지이 요소를 업데이트 v+(i==e)수단을 v+1인덱스 경우 i의는 acc현재 요소이다 e, 그렇지 않으면 이전 값v ;
  • 의 다음 요소 eL크기보다 크거나 같으면 새 호스트 acc를 확장 acc하도록 확장 해야합니다 1.

요소를 정렬 할 필요는 없습니다 ( itertools.groupby). 음수가 있으면 이상한 결과가 나옵니다.


0

세트를 사용하여 다른 방법을 찾았습니다.

#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

목록에서 고유 한 요소를 찾으려면

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

사전을 사용하여 정렬 된 배열에서 고유 한 요소 수를 찾으려면

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)

GeeksforGeeks 참조


-1

또 다른 방법은 사전과 list.count를 사용하여 순진한 방법으로 사용하는 것입니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.