Counter.most_common()

問題

怎樣找出一個序列中出現次數最多的元素呢?

解決方案
collections.Counter 類就是專門爲這類問題而設計的, 它甚至有一個有用的 most_common() 方法直接給了你答案。

爲了演示,先假設你有一個單詞列表並且想找出哪個單詞出現頻率最高。你可以這樣做:

words = [
    'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
    'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
    'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
    'my', 'eyes', "you're", 'under'
]
from collections import Counter
word_counts = Counter(words)
# 出現頻率最高的3個單詞
top_three = word_counts.most_common(3)
print(top_three)
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

討論
作爲輸入, Counter 對象可以接受任意的由可哈希(hashable)元素構成的序列對象。 在底層實現上,一個 Counter 對象就是一個字典,將元素映射到它出現的次數上。比如:

>>> word_counts['not']
1
>>> word_counts['eyes']
8
>>>
  • 1
  • 2
  • 3
  • 4
  • 5

如果你想手動增加計數,可以簡單的用加法:

>>> morewords = ['why','are','you','not','looking','in','my','eyes']
>>> for word in morewords:
...     word_counts[word] += 1
...
>>> word_counts['eyes']
9
>>>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

或者你可以使用 update() 方法:

>>> word_counts.update(morewords)
>>>
  • 1
  • 2

Counter 實例一個鮮爲人知的特性是它們可以很容易的跟數學運算操作相結合。比如:

>>> a = Counter(words)
>>> b = Counter(morewords)
>>> a
Counter({'eyes': 8, 'the': 5, 'look': 4, 'into': 3, 'my': 3, 'around': 2,
"you're": 1, "don't": 1, 'under': 1, 'not': 1})
>>> b
Counter({'eyes': 1, 'looking': 1, 'are': 1, 'in': 1, 'not': 1, 'you': 1,
'my': 1, 'why': 1})
>>> # Combine counts
>>> c = a + b
>>> c
Counter({'eyes': 9, 'the': 5, 'look': 4, 'my': 4, 'into': 3, 'not': 2,
'around': 2, "you're": 1, "don't": 1, 'in': 1, 'why': 1,
'looking': 1, 'are': 1, 'under': 1, 'you': 1})
>>> # Subtract counts
>>> d = a - b
>>> d
Counter({'eyes': 7, 'the': 5, 'look': 4, 'into': 3, 'my': 2, 'around': 2,
"you're": 1, "don't": 1, 'under': 1})
>>>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

毫無疑問, Counter 對象在幾乎所有需要製表或者計數數據的場合是非常有用的工具。 在解決這類問題的時候你應該優先選擇它,而不是手動的利用字典去實現。

1.collections模塊
collections模塊自Python 2.4版本開始被引入,包含了dict、set、list、tuple以外的一些特殊的容器類型,分別是:

OrderedDict類:排序字典,是字典的子類。引入自2.7。
namedtuple()函數:命名元組,是一個工廠函數。引入自2.6。
Counter類:爲hashable對象計數,是字典的子類。引入自2.7。
deque:雙向隊列。引入自2.4。
defaultdict:使用工廠函數創建字典,使不用考慮缺失的字典鍵。引入自2.5。

2.Counter類
Counter類的目的是用來跟蹤值出現的次數。它是一個無序的容器類型,以字典的鍵值對形式存儲,其中元素作爲key,其計數作爲value。計數值可以是任意的Interger(包括0和負數)。Counter類和其他語言的bags或multisets很相似。

2.1 創建
下面的代碼說明了Counter類創建的四種方法:

>>> c = Counter()  # 創建一個空的Counter類
>>> c = Counter('gallahad')  # 從一個可iterable對象(list、tuple、dict、字符串等)創建
>>> c = Counter({'a': 4, 'b': 2})  # 從一個字典對象創建
>>> c = Counter(a=4, b=2)  # 從一組鍵值對創建
  • 1
  • 2
  • 3
  • 4

2.2 計數值的訪問與缺失的鍵
當所訪問的鍵不存在時,返回0,而不是KeyError;否則返回它的計數。

>>> c = Counter("abcdefgab")
>>> c["a"]
2
>>> c["c"]
1
>>> c["h"]
0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.3 計數器的更新(update和subtract)
可以使用一個iterable對象或者另一個Counter對象來更新鍵值。
計數器的更新包括增加和減少兩種。其中,增加使用update()方法:

>>> c = Counter('which')
>>> c.update('witch')  # 使用另一個iterable對象更新
>>> c['h']
3
>>> d = Counter('watch')
>>> c.update(d)  # 使用另一個Counter對象更新
>>> c['h']
4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

減少則使用subtract()方法:

>>> c = Counter('which')
>>> c.subtract('witch')  # 使用另一個iterable對象更新
>>> c['h']
1
>>> d = Counter('watch')
>>> c.subtract(d)  # 使用另一個Counter對象更新
>>> c['a']
-1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.4 鍵的刪除
當計數值爲0時,並不意味着元素被刪除,刪除元素應當使用del

>>> c = Counter("abcdcba")
>>> c
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
>>> c["b"] = 0
>>> c
Counter({'a': 2, 'c': 2, 'd': 1, 'b': 0})
>>> del c["a"]
>>> c
Counter({'c': 2, 'b': 2, 'd': 1})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.5 elements()
返回一個迭代器。元素被重複了多少次,在該迭代器中就包含多少個該元素。元素排列無確定順序,個數小於1的元素不被包含。

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
  • 1
  • 2
  • 3

2.6 most_common([n])
返回一個TopN列表。如果n沒有被指定,則返回所有元素。當多個元素計數值相同時,排列是無確定順序的。

>>> c = Counter('abracadabra')
>>> c.most_common()
[('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
>>> c.most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
  • 1
  • 2
  • 3
  • 4
  • 5

2.7 淺拷貝copy

>>> c = Counter("abcdcba")
>>> c
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
>>> d = c.copy()
>>> d
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.8 算術和集合操作
+、-、&、|操作也可以用於Counter。其中&和|操作分別返回兩個Counter對象各元素的最小值和最大值。需要注意的是,得到的Counter對象將刪除小於1的元素。

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d  # c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d  # subtract(只保留正數計數的元素)
Counter({'a': 2})
>>> c & d  # 交集:  min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d  # 並集:  max(c[x], d[x])
Counter({'a': 3, 'b': 2})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.常用操作
下面是一些Counter類的常用操作,來源於Python官方文檔

sum(c.values())  # 所有計數的總數
c.clear()  # 重置Counter對象,注意不是刪除
list(c)  # 將c中的鍵轉爲列表
set(c)  # 將c中的鍵轉爲set
dict(c)  # 將c中的鍵值對轉爲字典
c.items()  # 轉爲(elem, cnt)格式的列表
Counter(dict(list_of_pairs))  # 從(elem, cnt)格式的列表轉換爲Counter類對象
c.most_common()[:-n:-1]  # 取出計數最少的n-1個元素
c += Counter()  # 移除0和負值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
                                </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章