pin_drop当前位置:知识文库 ❯ 图文

Python Counter计数器详解 - 词频统计与数据分析教程

一、概述

Countercollections 模块中的计数器类,它是 dict 的子类,专门用于统计可哈希对象的出现次数。Counter 将元素作为键,出现次数作为值,自动完成计数工作。它还提供了丰富的数学运算方法(加、减、交集、并集),使得频率统计和比较变得极为简便。Counter 是文本分析、数据统计、投票系统等场景的首选工具。


二、语法

代码示例

from collections import Counter

# 从可迭代对象创建
c = Counter(iterable)

# 从关键字参数创建
c = Counter(a=3, b=2, c=1)

# 从字典创建
c = Counter({"a": 3, "b": 2})

三、参数说明

构造函数参数

参数 类型 说明
iterable 可迭代对象 统计其中元素的出现次数
mapping dict/Counter 从映射创建计数器
**kwargs 关键字参数 键值对直接作为元素和计数

常用方法

方法 说明
c.elements() 返回所有元素的迭代器(按计数重复)
c.most_common(n=None) 返回出现次数最多的n个元素
c.subtract(other) 减去另一个计数器的计数(允许负数)
c.update(other) 加上另一个计数器的计数
c.total() 返回所有计数的总和(Python 3.10+)

数学运算

运算 说明 示例
c1 + c2 合并计数(取大值) Counter(a=3) + Counter(a=1) = Counter(a=4)
c1 - c2 相减计数(忽略负数) Counter(a=3) - Counter(a=1) = Counter(a=2)
c1 & c2 交集(取最小值) Counter(a=3) & Counter(a=1) = Counter(a=1)
c1 | c2 并集(取最大值) Counter(a=3) | Counter(a=1) = Counter(a=3)

四、返回值

  • 构造函数返回 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%

六、实际应用场景

  • 文本分析:统计词频、字符频率,进行文本相似度比较

  • 数据统计:统计用户行为频率、商品销量排名、投票结果

  • 数据对比:使用交集和并集运算比较两个数据集的重叠和差异


七、注意事项

注意1Counter 访问不存在的键时返回 0 而非引发 KeyError,这是与普通 dict 的重要区别。但删除键需要使用 del c[key]

注意2subtract() 方法允许计数为负数,而减法运算 c1 - c2 会自动忽略负数和零值。

注意3elements() 方法返回的迭代器中,元素的顺序是不确定的(按键的插入顺序),且计数为零或负数的元素不会出现。

注意4Countertotal() 方法在 Python 3.10 中才引入,早期版本需使用 sum(c.values()) 替代。

提示Counterdict 的子类,支持所有字典方法。但不应在 Counter 中存储零或负数的计数,除非确实需要。


八、相关方法对比

特性 Counter dict手动计数 pandas.value_counts numpy.bincount
自动计数
数学运算 内置 手动 有限 有限
负数支持 是(subtract)
内存效率 中等
适用类型 可哈希对象 可哈希对象 Series 整数数组
安装要求 标准库 内置 需安装 需安装

九、小结

  • 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()} 字典推导式。

标签: Counter 词频统计 collections 计数器 Python教程 most_common 文本分析

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Python collections模块详解 - 5大专用容器入门教程 下一篇: Python defaultdict默认字典详解 - 数据分组与嵌套字典教程

poll相关推荐