本系列是《NumPy 速通》的配套章节。

对一整组数据算个总账——求和、均值、最大最小、方差等等。这些操作叫聚合(aggregation),因为它们把一堆数"聚合"成一个数。本章重点:axis 参数(90% 的坑都在这)和"忽略 NaN"的两个变体。

基本聚合函数

import numpy as np

arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])

np.sum(arr)      # 31       总和
np.mean(arr)     # 3.875    平均
np.max(arr)      # 9        最大
np.min(arr)      # 1        最小
np.std(arr)      # 标准差(sqrt(方差))
np.var(arr)      # 方差
np.median(arr)   # 3.5      中位数(不受极端值影响)
np.prod(arr)     # 连乘
np.cumsum(arr)   # [3 4 8 9 14 23 25 31]  累积和

💡 均值 vs 中位数:均值对极端值(outlier)敏感,中位数稳健。工资数据被几个富豪拉高时,用中位数更能反映"普通人"水平。np.cumsum(累积和)常用于画累积分布、算前缀和。

⚠️ 灵魂警告:NaN 会污染聚合结果

data = np.array([1.0, 2.0, np.nan, 4.0])

np.mean(data)   # nan  ⚠️ 一个 nan 就毁掉整个均值!

解决方案——忽略 NaN 的版本(每个聚合函数都有):

np.nanmean(data)   # 2.333  忽略 nan 再平均
np.nansum(data)    # 7.0
np.nanmax(data)    # 4.0
np.nanstd(data)    # 忽略 nan 的标准差

真实数据(传感器、爬虫、问卷)几乎必然有缺失值。先 np.isnan(data).any() 检查,再用 nan 系列函数,是数据清洗的基本功。

⭐ axis 参数 —— 最关键的技能

二维数组聚合时,axis 决定"沿着哪个方向算":

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

np.sum(arr)             # 21        全部求和(不指定 axis → 所有元素)
np.sum(arr, axis=0)     # [5 7 9]   按列求和(每列纵向加总)
np.sum(arr, axis=1)     # [6 15]    按行求和(每行横向加总)

记忆技巧:axis=0 沿"行"方向压扁 → 结果是每列的聚合;axis=1 沿"列"方向压扁 → 结果是每行的聚合。

一个更稳的口诀:结果数组的 shape 里,axis 那一位被"压掉"了:

  • (3, 4) 配 axis=0 → (4,)(每列一个数)
  • (3, 4) 配 axis=1 → (3,)(每行一个数)

三维数组同理:np.sum(arr, axis=0) 把第 0 维压掉。

多维实战:5 位同学 × 3 门课

沿用贯穿案例:

scores = np.array([[90, 80, 85],   # 同学1:语 数 英
                   [60, 70, 65],
                   [95, 88, 92],
                   [72, 65, 78],
                   [55, 60, 70]])

scores.mean(axis=1)    # 每位同学平均分
# [85.  65.  91.66666667 71.66666667 61.66666667]

scores.mean(axis=0)    # 每门课平均分
# [74.4 72.6 78. ]   语文 74.4,数学 72.6,英语 78

scores.max(axis=0)     # 每门课最高分 [95 88 92]
scores.std(axis=1)     # 每位同学成绩波动(标准差)

axis=1 求"每个人",axis=0 求"每门课"——这是聚合最重要的两个方向。

找出最值的位置:argmax / argmin

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

np.argmax(arr)   # 5   最大值 9 在索引 5
np.argmin(arr)   # 1   最小值 1 在索引 1

# 二维配合 axis:找每列/每行的最值位置
np.argmax(scores, axis=0)   # [2 2 2]  每门课最高分在同学索引 2
np.argmax(scores, axis=1)   # [0 2 2 2 2]  每位同学哪门课最高

💡 argmax/argmin 返回**位置(索引)**而非值。机器学习里 np.argmax(model(x)) 就是"预测的类别"——分类问题最常用的收尾动作。

其它实用统计

np.percentile(arr, 90)     # 第 90 百分位数(90% 数据比它小)
np.percentile(arr, [25, 50, 75])  # 四分位数 Q1/Q2/Q3
np.ptp(arr)                # 极差 = max - min
np.corrcoef(x, y)          # 相关系数矩阵(两变量线性相关程度)
np.bincount(arr).argmax()  # 众数(出现最多的值)

💡 百分位数是"分位数"的通用版:np.percentile(data, 50) 就是中位数。画箱线图、看数据分布都要它。

方法 vs 函数:arr.sum() 与 np.sum(arr) 等价

arr.sum()        # 方法形式
np.sum(arr)      # 函数形式 —— 完全等价

两者都行,只是写法不同。np.sum 这种函数形式可以传任意数组,方法形式更"面向对象"。选一种保持风格一致即可。

小结

函数 作用 忽略 NaN 版本
sum / mean 和 / 平均 nansum / nanmean
max / min 最大 / 最小 nanmax / nanmin
std / var 标准差 / 方差 nanstd
median 中位数 nanmedian
argmax / argmin 最值位置 —
percentile 百分位数 nanpercentile
  1. ⚠️ NaN 会污染结果 → 用 nan 系列
  2. ⭐ axis=0 按列、axis=1 按行,压掉指定维度
  3. argmax 拿位置(索引),常用于分类预测
  4. arr.sum() 和 np.sum(arr) 等价

下一章:不同形状的数组怎么直接运算(广播)。


上一篇:第 6 章 通用函数 | 下一篇:第 8 章 广播机制