collections docs
본 포스팅은 공식문서를 읽고 정리하는 용도이며, Python 3.9를 기준으로 합니다
Collections.Couter tool은 편리하고, 빠른 집계 모듈이다.
즉, 더 간편한 dictionary라고 볼 수 있다.
아래 두 가지 예제를 통해 Counter의 기능을 알 수 있다.
# 리스트 내 단어의 등장 횟수 카운트
from Collections import Counter
cnt = Counter()
for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']
cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red':2, 'green': 1})
# 외부 파일 내 단어 수 카운트
import re
words = re.findall(r'\w+', open('halet.txt').read().lower())
>>> Counter(words).most_common(10) # 가장 많이 등장한 상위 10개의 item
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
dict 객체를 생성해서 list 혹은 document에서 for문을 적용하지 않고, Counter 를 사용함으로써 코드가 더 짧아지고, 코드를 더 직관적으로 읽을 수 있다.
Counter는 dict의 subclass이다. Counter는 hashable 개체를 카운트할 수 있다. 여기서 hashable이란 hash value를 가질 수 있는지를 나타낸다. 조금 어려운 개념이라 참고할 수 있는 블로그 링크를 걸어놓았다.
hashable과 mutable
Counter에서 hashable 개체가 중요한 이유는 중복방지, key탐색 등의 이유일 것이다. 중복방지의 경우, key값의 hash value가 같을 경우, 같은 값으로 인식하여 해당 hash value의 등장 횟수를 카운트한다.
Counter 는 elements들이 key로 저장되고, elements의 카운트 값이 value로 저장되는 collection이다. 여기서 value 값으로는 0 또는 음수 카운트를 포함한 모든 정수 값이 될 수 있다.
c = Counter() # empty counter 생성
c = Counter('gallahad') # iterable 개체로부터 counter 생성
c = Counter({'red': 4, 'blue': 2}) # mapping 개체로부터 counter 생성
c = Counter(cats=4, dogs=8) # keyword args 로부터 counter 생성
counter 객체 내에 없는 item을 input으로 주었을 때, Counter는 KeyError를 발생시키는 대신, 0을 리턴한다.
c = Counter(['eggs', 'ham'])
c['bacon']
>>> 0 #count of a missing element is zero
Counter 내의 요소를 삭제할 때는 del 을 사용해야한다.
del c['sausage']
Counter 는 dict의 subclass로서 삽입 순서를 기억하는 기능을 상속받음.
즉, 삽입 순서를 기억함.
element가 처음 발견된 순서에 따라 정렬된다.
dict의 subclass로서 모든 dict에 사용ㅇ할 수 있는 methods를 사용할 수 있다.
또한, 다음의 추가적인 methods를 지원한다.
Counter 객체 내 각 elements 의 수만큼 반복하여 iterator 를 리턴한다. elements는 처음 발견된 순서대로 리턴한다.
elements의 count 가 1 미만이면 리턴하지 않는다.
c = Counter(a=4, b=2, c=0, d=-2)
sorted(c.elements())
>>> ['a', 'a', 'a', 'a', 'b', 'b']
elements 중 가장 많이 count된 (value가 가장 높은) elements와 value를 리턴한다. n이 생략된경우, most_common()은 Counter 내 모든 elements를 리턴한다.
Counter('abracadabra').most_common(3)
>>> [('a', 5), ('b', 2), ('r', 2)]
각 elements에 대한 value를 감산(-)을 수행할 수 있다.
c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
c.subtract(d)
c
>>> Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
Counter 객체는 몇 가지 수학적 연산이 가능하다.
c = Counter(a=3, b=1)
d = Counter(a=1, b=2)
c+d # Counter()끼리의 덧셈
>>> Counter({'a':4, 'b':3})
c-d # Counter()끼리의 뺄셈
>>> Counter({'a':2})
c & d # 두 Counter() 객체 내 elements의 최솟값 value
>>> Counter({'a': 1, 'b': 1})
c | d # 두 Counter() 객체 내 elements의 최댓값 value
>>> Counter({'a': 3, 'b': 2})
fromkeys() method는 Counter에서는 구현되어있지 않다.
counter() 내 elements 들은 iterable 개체 혹은 mapping 개체를 통해 카운트된다. dict.update()와 달리 replacing되지 않는다.
또한, 여기서 iterable 이란 elements의 sequence로 기대된다. (key,value)페어는 될 수 없다.