pin_drop当前位置:知识文库 ❯ 图文
Python Counter计数器详解 - 词频统计与数据分析教程
一、概述
Counter 是 collections 模块中的计数器类,它是 dict 的子类,专门用于统计可哈希对象的出现次数。Counter 将元素作为键,出现次数作为值,自动完成计数工作。它还提供了丰富的数学运算方法(加、减、交集、并集),使得频率统计和比较变得极为简便。Counter 是文本分析、数据统计、投票系统等场景的首选工具。
二、语法
代码示例
from collections import Counter
# 从可迭代对象创建
c = Counter(iterable)
# 从关键字参数创建
c = Counter(a=3, b=2, c=1)
# 从字典创建
c = Counter({"a": 3, "b": 2})三、参数说明
构造函数参数
常用方法
数学运算
四、返回值
-
构造函数返回
Counter对象 -
elements()返回迭代器
-
most_common()返回
list[tuple] -
total()返回
int(Python 3.10+) -
数学运算返回新的
Counter对象
五、代码示例
示例1:基本计数操作
代码示例
from collections import Counter
# 从字符串创建
c1 = Counter("abracadabra")
print(f"字符串计数: {c1}")
print(f"最常见的3个: {c1.most_common(3)}")
# 从列表创建
c2 = Counter(["apple", "banana", "apple", "cherry", "banana", "apple"])
print(f"\n列表计数: {c2}")
# 访问计数
print(f"apple出现次数: {c2['apple']}")
print(f"orange出现次数: {c2['orange']}") # 不存在返回0,不引发KeyError
# elements() 获取所有元素
elements = list(c2.elements())
print(f"\n所有元素: {elements}")输出:
代码示例
字符串计数: Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
最常见的3个: [('a', 5), ('b', 2), ('r', 2)]
列表计数: Counter({'apple': 3, 'banana': 2, 'cherry': 1})
apple出现次数: 3
orange出现次数: 0
所有元素: ['apple', 'apple', 'apple', 'banana', 'banana', 'cherry']示例2:数学运算
代码示例
from collections import Counter
c1 = Counter(a=3, b=2, c=1)
c2 = Counter(a=1, b=3, d=2)
print(f"c1: {c1}")
print(f"c2: {c2}")
# 加法:合并计数
print(f"\nc1 + c2: {c1 + c2}")
# 减法:相减(忽略负数和零)
print(f"c1 - c2: {c1 - c2}")
# 交集:取最小值
print(f"c1 & c2: {c1 & c2}")
# 并集:取最大值
print(f"c1 | c2: {c1 | c2}")
# update 和 subtract
c3 = Counter(a=3, b=2)
c3.update({"a": 2, "c": 1})
print(f"\nupdate后: {c3}")
c4 = Counter(a=3, b=2)
c4.subtract({"a": 1, "b": 3})
print(f"subtract后: {c4}") # b=-1 允许负数输出:
代码示例
c1: Counter({'a': 3, 'b': 2, 'c': 1})
c2: Counter({'b': 3, 'd': 2, 'a': 1})
c1 + c2: Counter({'a': 4, 'b': 5, 'd': 2, 'c': 1})
c1 - c2: Counter({'a': 2, 'c': 1})
c1 & c2: Counter({'a': 1, 'b': 2})
c1 | c2: Counter({'a': 3, 'b': 3, 'd': 2, 'c': 1})
update后: Counter({'a': 5, 'b': 2, 'c': 1})
subtract后: Counter({'a': 2, 'b': -1})示例3:文本分析工具
代码示例
from collections import Counter
import re
class TextAnalyzer:
"""文本分析工具"""
def __init__(self, text):
self.text = text
self.words = re.findall(r'\b\w+\b', text.lower())
def word_frequency(self, top_n=10):
"""词频统计"""
return Counter(self.words).most_common(top_n)
def char_frequency(self):
"""字符频率统计"""
return Counter(self.text)
def word_count(self):
"""总词数"""
return len(self.words)
def unique_words(self):
"""不重复词数"""
return len(set(self.words))
def compare(self, other_text):
"""比较两段文本的词汇重叠度"""
other_words = set(re.findall(r'\b\w+\b', other_text.lower()))
common = set(self.words) & other_words
ratio = len(common) / len(set(self.words)) if self.words else 0
return len(common), ratio
# 使用示例
text1 = "Python is a great programming language. Python is easy to learn. Python is powerful."
text2 = "Java is a popular programming language. Java is widely used in enterprise."
analyzer = TextAnalyzer(text1)
print("词频统计:")
for word, count in analyzer.word_frequency(5):
print(f" {word}: {count}")
print(f"\n总词数: {analyzer.word_count()}")
print(f"不重复词数: {analyzer.unique_words()}")
common, ratio = analyzer.compare(text2)
print(f"\n与text2共同词汇: {common}个, 重叠率: {ratio:.1%}")输出:
代码示例
词频统计:
python: 3
is: 3
a: 1
great: 1
programming: 1
总词数: 13
不重复词数: 9
与text2共同词汇: 4个, 重叠率: 44.4%六、实际应用场景
-
文本分析:统计词频、字符频率,进行文本相似度比较
-
数据统计:统计用户行为频率、商品销量排名、投票结果
-
数据对比:使用交集和并集运算比较两个数据集的重叠和差异
七、注意事项
注意1:
Counter访问不存在的键时返回 0 而非引发KeyError,这是与普通dict的重要区别。但删除键需要使用del c[key]。
注意2:
subtract()方法允许计数为负数,而减法运算c1 - c2会自动忽略负数和零值。
注意3:
elements()方法返回的迭代器中,元素的顺序是不确定的(按键的插入顺序),且计数为零或负数的元素不会出现。
注意4:
Counter的total()方法在 Python 3.10 中才引入,早期版本需使用sum(c.values())替代。
提示:
Counter是dict的子类,支持所有字典方法。但不应在Counter中存储零或负数的计数,除非确实需要。
八、相关方法对比
九、小结
-
Counter是专用于计数的字典子类,自动统计元素出现次数 -
核心方法:
most_common()(排名)、elements()(展开)、update()/subtract()(增减) -
支持四种数学运算:加法、减法、交集、并集,便于数据比较
-
访问不存在的键返回 0,不会引发
KeyError
十、练习题
练习1
编写一个函数 find_anagrams(words),使用 Counter 找出列表中所有互为字母异位词的单词组。
练习2
编写一个函数 top_k_frequent(nums, k),使用 Counter 找出数组中出现频率最高的前 k 个元素,要求时间复杂度优于 O(n log n)。
练习3
编写一个函数 inventory_diff(old, new),使用 Counter 的减法运算计算两个库存清单的差异(新增、减少、不变的商品及数量)。
常见问题
Counter访问不存在的键为什么返回0而不是报错?
因为 Counter 重写了 __missing__ 方法,这是它作为计数器的核心设计。对于不存在的元素,其计数自然为 0,这样在累加和统计时不需要频繁检查键是否存在,代码更简洁。
Counter的减法运算和subtract()方法有什么区别?
c1 - c2 会忽略结果中的负数和零值,而 c1.subtract(c2) 会原地修改 c1 并保留负数。如果只需要正数结果,使用减法运算符;如果需要追踪减少量,使用 subtract()。
most_common()的时间复杂度是多少?
most_common(n) 使用堆排序,时间复杂度为 O(n log k),其中 n 是唯一元素数量,k 是请求的 top-k 数量。当不传参数时,使用排序算法,时间复杂度为 O(n log n)。
Counter可以用于不可哈希对象吗?
不行。Counter 的键必须是可哈希的(hashable),因为底层使用字典实现。如果需要对列表等不可哈希对象计数,需要先将其转换为元组或其他可哈希类型。
如何将Counter转换为普通字典?
因为 Counter 是 dict 的子类,直接使用 dict(counter) 即可转换。也可以使用 {k: v for k, v in counter.items()} 字典推导式。
本文涉及AI创作
内容由AI创作,请仔细甄别