场景1: 某序列[2, 4, 65, 9, 4, 5, 9, …]中,找出出现次数最高的3个元素以及它们出现的次数
场景2:对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词以及它们出现的次数
我们经常会遇到上述场景,实现的方法有多种,这里介绍一下常用的处理方法和几个好用的函数。
找出list出现次数最多的值以及出现的次数
使用列表解析生成30个数字元素的list列表,每个元素范围在0~20之间,这样肯定就会出现重复值的元素:
from random import randint
data = [randint(0,20) for i in range(30)]
# [17, 3, 18, 18, 0, 8, 11, 16, 2, 13, 8, 16, 16, 10, 19, 2, 16, 17, 20, 9, 17, 19, 15, 16, 10, 18, 16, 10, 0, 2]
我们希望最终统计结果是一个字典,比如3出现了4次,9出现了2次这样:{3:4, 9:2…}
方法1
我们就用data中的每一个元素作为key(利用key的唯一性),0作为初始值创建字典:
d1 = dict.fromkeys(data, 0)
接下来对列表data进行迭代,每个值都在字典对应的值加1,这样就统计出每个值出现的次数了。
for i in data:
d1[i] +=1
print(d1) # {0: 0, 2: 0, 3: 0, 8: 0, 9: 0, 10: 0, 11: 0, 13: 0, 15: 0, 16: 0, 17: 0, 18: 0, 19: 0, 20: 0}
接下来我们需要找到出现次数最高的3个元素,实际上就是根据字典的值对字典的项进行排序。
方法2
这里我们使用另外一种专门处理这类问题的方法:使用collections.Counter对象。
将前面创建的list传入Counter构造器,得到Counter对象是元素频度的字典:
from collections import Counter
d2 = Counter(data)
print(d1[15] == d2[15]) # 验证两种方法中的字典统计的list的15这个值出现的次数是否一样
接着用Counter.most_common(n)方法得到频度最高的n个元素的列表。
这里我们需要找到出现频率最高的3个元素以及出现的次数:
print(d2.most_common(3)) # [(16, 6), (2, 3), (10, 3)]
使用collections.Counter对象,处理这类问题非常简洁清晰,封装了list处理逻辑细节,增强代码的易读性。
对英文文章进行词频统计
这里以一首英文短诗为例,来进行词频统计。
txt = '''If I could save time in a bottle
the first thing that I'd like to do
is to save every day until eternity passes away
just to spend them with you
If I could make days last forever
if words could make wishes come true
I'd save every day like a treasure and then
again I would spend them with you'''
要对词频进行统计,首先要对词做分割,把每个词取出来,放到一个序列当中。
我们使用正则表达式来进行分割,用非字母字符作为分隔符:
import re
list = re.split('\W+', txt) # 大写W表示是非字母字符
这里得到一个单词列表list,我们将list传给前面提到的Counter,得到单词词频的字典d3:
from collections import Counter
d3 = Counter(list)
这里我们统计词频最高的10个单词,打印一下:
print(d3.most_common(10)) # [('I', 5), ('save', 3), ('could', 3), ('to', 3), ('If', 2), ('like', 2), ('them', 2), ('make', 2), ('spend', 2), ('every', 2)]