使用Counter进行计数统计
想必大家对计数统计都不陌生吧!,简单的说就是统计某一项出现的次数。实际应用中很多需求都需要用到这个模型,如检测样本中某一值出现的次数、日志分析某一消息出现的频率分析文件中相同字符串出现的概率等。这类似的需求有很多种实现方法。我们逐一来看一下使用不同数据结构是的实现方式
一、使用dict
首先来看看dict这种方法实现,废话不多说,先看看这个小小的骚操作,后面的操作会让你大大底爽一下,彻底的让你满足,请看表演:
some_data = [\'a\', \'2\', 2, 4, 5, \'2\', \'b\', 4, 7, \'a\', \'5\', \'d\', \'a\', \'z\'] # 创建列表
count_frq = dict() # 创建列表
# 词频统计
for item in some_data:
if item in count_frq:
count_frq[item] += 1
else:
count_frq[item] = 1
print(count_frq)
结果:
{\'a\': 3, \'2\': 2, 2: 1, 4: 2, 5: 1, \'b\': 1, 7: 1, \'5\': 1, \'d\': 1, \'z\': 1}
二、使用set和list方法
再看看这个常用的小方法
some_data = [\'a\', \'2\', 2, 4, 5, \'2\', \'b\', 4, 7, \'a\', \'5\', \'d\', \'a\', \'z\']
count_set = set(some_data) # 去重
count_list = []
for item in count_set:
count_list.append((item, some_data.count(item))) # 添加
print(count_list)
结果:
[(\'5\', 1), (2, 1), (\'2\', 2), (4, 2), (5, 1), (7, 1), (\'a\', 3), (\'z\', 1), (\'b\', 1), (\'d\', 1)]
三、collections使用
上面的方法都比较简单,但有没有更优雅,更骚气的,更Pythonic的解决方法呢?请看下面的引入defaultdict
1.1 defaultdict
from collections import defaultdict
some_data = [\'a\', \'2\', 2, 4, 5, \'2\', \'b\', 4, 7, \'a\', \'5\', \'d\', \'a\', \'z\']
count_frq = defaultdict(int) # defaultdict(int)
# 统计计数
for item in some_data:
count_frq[item] += 1
print(count_frq)
结果:
dict_items([(\'a\', 3), (\'2\', 2), (2, 1), (4, 2), (5, 1), (\'b\', 1), (7, 1), (\'5\', 1), (\'d\', 1), (\'z\', 1)])
1.2 Counter
Counter 类是自Python2.7起增加的,属于字典类的子类,是一个容器对象,主要用来统计# 散列对象,支持集合操作 +、-、&、|,其中&和|操作分别返回两个Counter对象各元素# 的最大值和最小值。他提供3中不同的方式来初始化,正点来了,看看这个神奇的操作,代码行度大大缩减:
from collections import Counter
some_data = [\'a\', \'2\', 2, 4, 5, \'2\', \'b\', 4, 7, \'a\', \'5\', \'d\', \'a\', \'z\']
count_counter = Counter(some_data) # 统计
print(count_counter) # 结果就出来,就问你强不强
结果:
Counter({\'a\': 3, \'2\': 2, 4: 2, 2: 1, 5: 1, \'b\': 1, 7: 1, \'5\': 1, \'d\': 1, \'z\': 1})
- Counter不仅可以对列表就行统计,他可以对任何可以迭代的对象进行统计如下:
-
可迭代的对象字符串
Counter("success") # 可迭代对象 print(Counter("success"))结果:
Counter({\'s\': 3, \'c\': 2, \'u\': 1, \'e\': 1})
-
关键字参数
Counter(s=3, c=2, e=1, u=1) # 关键字参数
print(Counter(s=3, c=2, e=1, u=1))
结果:
Counter({\'s\': 3, \'c\': 2, \'e\': 1, \'u\': 1})
- 字典
Counter({\'s\': 3, \'c\': 2, \'e\': 1, \'u\': 1})
print(Counter({\'s\': 3, \'c\': 2, \'e\': 1, \'u\': 1}))
结果:
Counter({\'s\': 3, \'c\': 2, \'e\': 1, \'u\': 1})
-
可以使用elements()方法获取Counter中的key值
print(list(Counter(some_data).elements())) # 根据值打印key的次数结果:
[\'a\', \'a\', \'a\', \'2\', \'2\', 2, 4, 4, 5, \'b\', 7, \'5\', \'d\', \'z\']
-
看看一个更骚气的方法,利用most_commo()方法可以找前N个出现频率最高的元素以及他们对应的次数。
count = Counter(some_data).most_common(2) # 获取前两个频率最高 print(count)结果:
[(\'a\', 3), (\'2\', 2)]
-
当访问不存在的元素是,默认返回0而不是抛出keyError异常
print(Counter(some_data)["y"])结果:
0
-
update()方法用于被统计对象元素的更新,原有Counter计数器对象与新增元素的统计计数值相加而不是直接替换她们
c = Counter("success") print(c)结果:
Counter({\'s\': 3, \'c\': 2, \'u\': 1, \'e\': 1})
在此基础上进行更新
c.update("successfully") print(c)Counter({\'s\': 6, \'c\': 4, \'u\': 3, \'e\': 2, \'l\': 2, \'f\': 1, \'y\': 1})
-
subtract()方法用于实现计数器对象中元素统计值相减,输入输出的统计值允许为0或者负数(在更新的基础上进行相减)
c = Counter("success") print(c)结果:
Counter({\'s\': 3, \'c\': 2, \'u\': 1, \'e\': 1, \'f\': 0, \'l\': 0, \'y\': 0})
用兴趣的可以自己研究下哦!