NumPy 聚合函数

聚合函数(也称为归约函数)是对一组数值进行汇总计算,返回单个或少量统计结果的函数。NumPy提供了丰富的聚合函数,可以快速计算数组的总和、均值、最大值、最小值等统计量,并且支持沿指定轴进行聚合。

1. 基本聚合函数

以下是最常用的聚合函数,它们默认将整个数组归约为一个标量值。

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
print("数组:\n", arr)

print("总和 (np.sum):", np.sum(arr))
print("均值 (np.mean):", np.mean(arr))
print("最大值 (np.max):", np.max(arr))
print("最小值 (np.min):", np.min(arr))
print("标准差 (np.std):", np.std(arr))
print("方差 (np.var):", np.var(arr))
print("乘积 (np.prod):", np.prod(arr))          # 所有元素乘积 1*2*3*4*5*6 = 720
print("中位数 (np.median):", np.median(arr))    # 中位数 (3+4)/2 = 3.5

输出:

数组:
 [[1 2 3]
 [4 5 6]]
总和 (np.sum): 21
均值 (np.mean): 3.5
最大值 (np.max): 6
最小值 (np.min): 1
标准差 (np.std): 1.707825127659933
方差 (np.var): 2.9166666666666665
乘积 (np.prod): 720
中位数 (np.median): 3.5

2. 轴参数 (axis) 与 keepdims

通过 axis 参数可以指定沿哪个轴进行聚合。例如,对于二维数组,axis=0 表示沿行方向(即每一列),axis=1 表示沿列方向(即每一行)。keepdims=True 可以保持原数组的维度,结果仍具有与原数组相同的维度数(大小为1的轴)。

arr = np.array([[1, 2, 3], [4, 5, 6]])
print("原数组 shape:", arr.shape)

# 沿列求和 (axis=0) -> 结果是一维数组,长度为列数
sum_axis0 = np.sum(arr, axis=0)
print("沿列求和 (axis=0):", sum_axis0, "shape:", sum_axis0.shape)

# 沿行求和 (axis=1)
sum_axis1 = np.sum(arr, axis=1)
print("沿行求和 (axis=1):", sum_axis1, "shape:", sum_axis1.shape)

# 使用 keepdims 保持维度
sum_keepdims = np.sum(arr, axis=1, keepdims=True)
print("沿行求和 keepdims=True:\n", sum_keepdims, "shape:", sum_keepdims.shape)

输出:

原数组 shape: (2, 3)
沿列求和 (axis=0): [5 7 9] shape: (3,)
沿行求和 (axis=1): [ 6 15] shape: (2,)
沿行求和 keepdims=True:
 [[ 6]
 [15]] shape: (2, 1)

注意:对于 np.median,它也有 axis 参数,但可能不支持 keepdims(版本差异)。

3. 多个聚合函数同时使用

除了单独调用每个函数,NumPy还提供了一些函数可以同时计算多个统计量,例如 np.aminnp.amaxminmax 的别名。对于同时需要多个值的情况,可以分别调用。

arr = np.array([1, 5, 3, 8, 2])

print("最小值:", np.amin(arr))
print("最大值:", np.amax(arr))
print("最小值索引:", np.argmin(arr))   # 返回最小值的索引
print("最大值索引:", np.argmax(arr))

输出:

最小值: 1
最大值: 8
最小值索引: 0
最大值索引: 3

4. NaN安全聚合函数

当数组中包含 NaN(Not a Number)值时,普通聚合函数会返回 NaN。NumPy提供了一系列忽略 NaN 的版本,函数名以 nan 开头。

arr_with_nan = np.array([1, 2, np.nan, 4, 5])

print("普通 sum:", np.sum(arr_with_nan))          # nan
print("nan sum:", np.nansum(arr_with_nan))        # 12.0
print("nan mean:", np.nanmean(arr_with_nan))      # 3.0
print("nan max:", np.nanmax(arr_with_nan))        # 5.0
print("nan min:", np.nanmin(arr_with_nan))        # 1.0
print("nan std:", np.nanstd(arr_with_nan))        # 1.58113883
print("nan median:", np.nanmedian(arr_with_nan))  # 3.0

输出:

普通 sum: nan
nan sum: 12.0
nan mean: 3.0
nan max: 5.0
nan min: 1.0
nan std: 1.5811388300841898
nan median: 3.0

5. 累积聚合函数

累积函数返回一个与输入形状相同的数组,每个元素是到当前位置的聚合结果。常用的有 cumsum(累积和)和 cumprod(累积积)。

arr = np.array([1, 2, 3, 4])
print("原数组:", arr)
print("累积和 (cumsum):", np.cumsum(arr))        # [1 3 6 10]
print("累积积 (cumprod):", np.cumprod(arr))      # [1 2 6 24]

# 二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组累积和 (axis=0):\n", np.cumsum(arr2d, axis=0))
print("二维数组累积和 (axis=1):\n", np.cumsum(arr2d, axis=1))

输出:

原数组: [1 2 3 4]
累积和 (cumsum): [1 3 6 10]
累积积 (cumprod): [1 2 6 24]
二维数组累积和 (axis=0):
 [[1 2 3]
 [5 7 9]]
二维数组累积和 (axis=1):
 [[1 3 6]
 [4 9 15]]

6. 其他常用聚合函数

  • np.ptp():峰峰值(最大值与最小值之差)
  • np.percentile():计算百分位数
  • np.quantile():计算分位数(与 percentile 类似,但用 [0,1] 区间)
  • np.average():加权平均
  • np.all():所有元素是否为 True
  • np.any():是否存在 True 元素
arr = np.array([1, 3, 5, 7, 9])

print("ptp (峰峰值):", np.ptp(arr))                    # 9-1 = 8
print("50% 分位数 (中位数):", np.percentile(arr, 50))   # 5.0
print("0.5 分位数 (中位数):", np.quantile(arr, 0.5))    # 5.0

# 加权平均
weights = np.array([0.1, 0.2, 0.3, 0.2, 0.2])
print("加权平均:", np.average(arr, weights=weights))

# 布尔聚合
bool_arr = np.array([True, False, True, True])
print("all:", np.all(bool_arr))    # False
print("any:", np.any(bool_arr))    # True

输出:

ptp (峰峰值): 8
50% 分位数 (中位数): 5.0
0.5 分位数 (中位数): 5.0
加权平均: 5.2
all: False
any: True

7. 性能注意事项

  • 聚合函数通常是用C实现的,非常高效。对于大型数组,应优先使用内置聚合函数而非Python循环。
  • 使用 axis 参数时,尽量选择内存布局连续的轴(通常 axis=1 对于行主序的C风格数组更高效)。
  • 对于同时需要多个聚合值(如总和、均值、最大值),分别调用多个函数通常比自定义循环更快,因为每个函数都是优化的。
  • 如果数组非常大且内存紧张,可以考虑使用 out 参数将结果写入预先分配的数组。
提示: 许多聚合函数也有对应的 ndarray 方法,例如 arr.sum()arr.mean(),使用起来更简洁。

总结

聚合函数是数据分析的基础工具。NumPy提供了全面且高效的聚合函数,配合 axis 参数可以灵活地进行分组汇总。掌握这些函数,你就能快速获取数组的统计特征,为后续的数据处理和分析打下坚实基础。下一章我们将学习NumPy的高级特性——广播机制。