统计次数
Pythora 星球的居民经常使用 Python 进行一些数据处理,其中常见的一个典型应用是统计输入数据中,每个条目出现了几次。对于这个简单的算法,也有很多种实现方法。
字典
最朴素的方式就是使用 Python 自带的字典数据类型进行统计:
elements = ['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果']
counts = {}
for element in elements:
if element in counts:
counts[element] += 1
else:
counts[element] = 1
print(counts)
在介绍字典数据类型时,我们提到:可以使用字典的两个方法,避免自己编程检查一个元素是否已经在字典中了。使用字典现有的方法可以简化代码:
elements = ['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果']
counts = {}
for element in elements:
counts.setdefault(element, 0)
counts[element] += 1
print(counts)
更好一点:
elements = ['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果']
counts = {}
for element in elements:
counts[element] = counts.get(element, 0) + 1
print(counts)
defaultdict 类
除了通用的字典数据类型,我们还可以使用一些为特殊需求设计的类,来简化特定的问题。比如针对字 典中缺失的键的默认值,我们可以使用 collections 模块中的一个名为 defaultdict 的子类,它继承自内置的 dict 类。defaultdict 的特点是它可以为字典中的键提供一个默认的函数,当用户尝试访问一个不存在的键时,defaultdict 会自动调用那个函数,生成生成一个默认值。比如,函数 int() 会返回一个整数 0,如果以此为默认值生成函数,那么缺失的键的默认值就都是 0。由于默认值是由一个函数的返回值确定的,而不是某个固定值,这意味着我们可以设计一个函数,让每个键拥有不同的默认值。
from collections import defaultdict
# 创建一个默认值为 int 的 defaultdict,这里 int() 返回 0
int_defaultdict = defaultdict(int)
# 创建一个默认值为 list 的 defaultdict,这里 list() 返回空列表 []
list_defaultdict = defaultdict(list)
# 匿名函数的功能是每次调用返回的整数都增加一,也就是在这个 defaultdict 中,
# 第一个缺失的键的默认值是 0,第二个的默认值是 1,以此类推
inc_defaultdict = defaultdict(lambda x=[]: x.append(len(x)) or x[-1])
# 测试:
print(inc_defaultdict["a"]) # 默认值为 0
print(inc_defaultdict["a"]) # 已使用过,读取已经设置的值
print(inc_defaultdict["b"]) # 默认值为 1
print(inc_defaultdict["c"]) # 默认值为 2
defaultdict 特别适用于那些需要字典中的每个键都必须有一个默认值的场景,例如在进行分组或计数时,这样就无需事先检查键是否存在。
比如计数:
from collections import defaultdict
elements = ['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果']
counts = defaultdict(int)
for element in elements:
counts[element] += 1
print(dict(counts)) # 输出: {'苹果': 3, '香蕉': 2, '桔子': 1}
分组也很适用,比如把一些输入的名字按照首字母分组:
from collections import defaultdict
surnames = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis']
names_by_first_letter = defaultdict(list)
for surname in surnames:
first_letter = surname[0]
names_by_first_letter[first_letter].append(surname)
print(dict(names_by_first_letter))
# 输出: {'S': ['Smith'], 'J': ['Johnson', 'Jones'], 'W': ['Williams'], 'B': ['Brown'], 'D': ['Davis']}
Counter 类
Python 中还带有一个专门由于统计计数的字典的子类 Counter。使用它进行计数更简洁:
from collections import Counter
elements = ['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果']
counts = Counter(elements)
print(counts) # 输出: Counter({'苹果': 3, '香蕉': 2, '桔子': 1})
Counter 作为专用于计数的类,它的功能就不仅仅局限于数出个数,还提供了一些与计数相关的高级功能,比如, most_common 方法,可以快速找出序列中出现次数最多的元素。
from collections import Counter
counts = Counter(['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果'])
# 最常见的 2 个元素:
print(counts.most_common(2)) # 输出: [('苹果', 3), ('香蕉', 2)]
Counter 类还重载了加法 +
、减法 -
、交集 &
和并集 |
运算符,用于对计数器进行相应的数学运算:
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
# 加法
c1 + c2 # 输出: Counter({'a': 4, 'b': 3})
# 减法
c1 - c2 # 输出: Counter({'a': 2})
# 交集
c1 & c2 # 输出: Counter({'a': 1, 'b': 1})
# 并集
c1 | c2 # 输出: Counter({'a': 3, 'b': 2})
pandas 库
Python 中进行数据分析,是离不开 pandas 库的。它是一个开源的数据分析库,提供了高性能、易用的数据结构和数据分析工具。它是基于 numpy 库构建的,并且密切集成了 matplotlib(用于绘图)和 scipy(用于科学计算)等库。对于这个库的详细介绍,可以参考数据分析和 Pandas 一节。
如果已经在项目里使用了 pandas 库,那么也可以直接使用它提供的一些类和方法进行计数。
如果你在处理大型数据集,pandas 库也提供了便捷的方法来计数:
value_counts()
pandas 提供了一个 Series 数据结构,用于存储一维数组。value_counts() 是 Series 对象的一个方法,用于返回不同值的出现频率。此方法默认返回频率降序排序。首先把输入转换成 Series 类型的对象,之后就可以调用 value_counts 进行计数了。
import pandas as pd
# 创建一个 Series 对象
s = pd.Series(['苹果', '香蕉', '苹果', '桔子', '香蕉', '苹果'])
# 使用 value_counts() 计数
counts = s.value_counts()
print(counts)
# 输出:
# 苹果 3
# 香蕉 2
# 桔子 1
# dtype: int64