第 6 章 轴与统计
学习目标
- 理解
axis(轴)的含义,掌握按轴聚合 - 掌握常用统计函数:
sum、mean、median、max、min、std、var - 掌握
cumsum、prod与argmax - 会用
keepdims保持维度
6.1 什么是轴(axis)
轴(axis)是数组的维度方向。二维数组有两个轴:axis=0 沿行方向(从上到下,跨行),axis=1 沿列方向(从左到右,跨列)。
用 4 个学生 × 3 门课的成绩表理解。行是学生,列是课程:
import numpy as np
scores = np.array([[85, 90, 78], # 学生 1:语文 数学 英语
[92, 88, 95], # 学生 2
[76, 84, 80], # 学生 3
[88, 91, 87]]) # 学生 4
print(scores.shape)输出:
(4, 3)scores.mean(axis=0) 沿行方向聚合:对每一列(同一门课)的 4 个学生求平均,结果是「每门课的平均分」,长度 3。
scores.mean(axis=1) 沿列方向聚合:对每一行(同一个学生)的 3 门课求平均,结果是「每个学生的平均分」,长度 4。
import numpy as np
print(scores.mean(axis=0)) # 每门课的平均分(列平均)
print(scores.mean(axis=1)) # 每个学生的平均分(行平均)输出:
[85.25 88.25 85. ]
[84.33333333 91.66666667 80. 88.66666667]记忆法:哪个轴=哪个方向,聚合后该维度消失。
axis=0聚合后,shape 从(4, 3)变成(3,):行维度(4)消失。axis=1聚合后,shape 从(4, 3)变成(4,):列维度(3)消失。
不指定 axis 时,聚合作用于所有元素,结果是一个标量:scores.mean() 是全部 12 个分数的平均(86.166...)。
6.2 常用统计函数
一维数组上,统计函数作用于全部元素:
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print("总和:", a.sum())
print("平均:", a.mean())
print("标准差:", a.std())
print("方差:", a.var())输出:
总和: 15
平均: 3.0
标准差: 1.4142135623730951
方差: 2.0标准差(std)衡量数据偏离平均值的程度,方差是标准差的平方。数据越分散,std 越大。二维数组按轴统计:
import numpy as np
scores = np.array([[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
[88, 91, 87]])
print(scores.sum(axis=0)) # 每门课总分
print(scores.max(axis=0)) # 每门课最高分
print(scores.max(axis=1)) # 每个学生最高分
print(np.median(scores, axis=0)) # 每门课中位数
print(np.std(scores, axis=0)) # 每门课标准差输出:
[341 353 340]
[92 91 95]
[90 95 84 91]
[86.5 89. 83.5]
[5.88960949 2.68095132 6.67083203]注意 median、std 等函数既可以写成 np.median(a),也可以写成方法 a.std();sum/mean/max/min 两者都行,median 只有函数形式。
标准差含义示例:英语课(std≈6.67)学生差异最大,数学课(std≈2.68)最平均——std 越大,这组数越分散。
6.3 cumsum 与 prod
cumsum(累计和):前 n 个元素之和组成的数组。
prod(乘积):全部元素相乘。
import numpy as np
print(np.cumsum(np.array([1, 2, 3, 4])))
print(np.prod(np.array([1, 2, 3, 4])))输出:
[ 1 3 6 10]
24cumsum 适合看「累计进度」,比如月度累计销量:
import numpy as np
monthly = np.array([120, 95, 150, 80]) # 每月销量
print(np.cumsum(monthly)) # 累计销量输出:
[120 215 365 445]6.4 argmax 与 argmin
argmax(数组, axis=...) 返回最大值的下标(而不是最大值本身),argmin 同理。
import numpy as np
scores = np.array([[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
[88, 91, 87]])
print(scores.argmax(axis=0)) # 每门课最高分是哪个学生(行号)输出:
[1 3 1]解读:语文最高分是学生下标 1(92 分),数学是下标 3(91 分),英语是下标 1(95 分)。
6.5 keepdims:聚合后保留维度
keepdims=True 让聚合结果保留原轴的维度(变成长度 1),方便后续与原始数组做形状兼容的运算:
import numpy as np
scores = np.array([[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
[88, 91, 87]])
print(scores.mean(axis=0))
print(scores.mean(axis=0, keepdims=True)) # 形状 (1, 3)输出:
[85.25 88.25 85. ]
[[85.25 88.25 85. ]]带 keepdims 的结果是 (1, 3),可以直接与 (4, 3) 的数组按广播规则运算(第 7 章),例如求每个分数相对本门课平均分的差值:
import numpy as np
scores = np.array([[85, 90, 78],
[92, 88, 95],
[76, 84, 80],
[88, 91, 87]])
course_mean = scores.mean(axis=0, keepdims=True)
print(scores - course_mean)输出:
[[-0.25 1.75 -7. ]
[ 6.75 -0.25 10. ]
[-9.25 -4.25 -5. ]
[ 2.75 2.75 2. ]]动手实践
- 创建 3×3 成绩表(自己设计数据),分别计算:全部平均、每列平均、每行平均,并解释三个结果分别代表什么。
- 用
std(axis=0)找出一组学生数据中「哪门课差距最大」。 - 计算 4 个学生每人 3 门课的总分与平均分,验证「行平均 × 3 = 行总分」。
- 用
argmax(axis=1)找出每个学生最高分对应的是哪门课(下标 0/1/2)。
常见错误
| 错误写法 | 现象 | 原因 |
|---|---|---|
| 混淆 axis=0 与 axis=1 的方向 | 统计结果含义反了 | axis=0 沿行方向聚合(按列统计),axis=1 沿列方向聚合(按行统计) |
| 忘记聚合后维度消失 | 形状对不上 | axis=0 聚合把行数变没了;需要保留用 keepdims=True |
np.median(a) 写成 a.median() | AttributeError: 'ndarray' object has no attribute 'median' | median 没有方法形式,要用 np.median(a) |
| 期望 std 衡量「平均数的差距」 | 概念混淆 | std 是离散程度;平均差距概念用 np.abs(a - a.mean()).mean() |
| 不指定 axis 时 | 得到全数组的标量 | 对多维数组要明确 axis,否则聚合所有元素 |
章末练习
基础
- 对
np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])计算:全部总和、axis=0总和、axis=1总和。 - 计算
np.array([4, 8, 6, 5, 3])的平均值与标准差。 - 用
cumsum计算[10, 20, 15, 5]的累计和。
提高
- 某班 5 名学生 4 门课成绩(自行设计),求:每门课平均分、每个学生总分、全班最高分及它所在位置(用
argmax)。 - 用
keepdims=True计算每列平均,再用原始数组减它,得到「每门课相对平均分的差值」。
挑战
- 生成
np.arange(1, 25).reshape(4, 6),不写循环,计算每行的最大值、每列的最大值,以及整个数组的最大值与它的位置(提示:np.unravel_index(np.argmax(a), a.shape))。 - 用
np.std对比[1, 2, 3, 4, 5]与[1, 1, 1, 5, 5]两组数的离散程度,并解释为什么。
章末自测
每题选择一个最佳答案。本书不附答案:完成后交由老师或 AI 老师批改讲解。
a = np.array([[1, 2], [3, 4]]); a.sum(axis=0)的结果是?- A.
[4, 6] - B.
[3, 7] - C.
10 - D.
[1, 2, 3, 4]
- A.
a.sum(axis=1)的结果是?- A.
[4, 6] - B.
[3, 7] - C.
10 - D.
[1, 2, 3, 4]
- A.
- 不指定 axis 时,
a.sum()的结果是?- A.
[4, 6] - B.
[3, 7] - C.
10 - D. 报错
- A.
np.median(a)的正确调用方式是?- A.
a.median() - B.
np.median(a) - C. 两者都可以
- D.
median(a)
- A.
- 标准差衡量的是?
- A. 数据总和
- B. 数据偏离平均值的程度
- C. 数据个数
- D. 最大值
keepdims=True的作用是?- A. 让聚合结果保留长度为 1 的维度
- B. 让聚合速度更快
- C. 只统计非零元素
- D. 返回视图
np.cumsum(np.array([1, 2, 3]))的结果是?- A.
[1, 2, 3] - B.
[1, 3, 6] - C.
6 - D.
[1, 2, 3, 6]
- A.
np.argmax(np.array([3, 7, 5]))的结果是?- A.
7 - B.
1 - C.
2 - D.
3
- A.
- 形状
(4, 3)的数组做mean(axis=0)后形状是?- A.
(4,) - B.
(3,) - C.
(4, 3) - D.
()
- A.
- 全班 3 门课成绩按列求平均,应使用?
- A.
scores.mean(axis=0) - B.
scores.mean(axis=1) - C.
scores.mean() - D.
scores.median(axis=1)
- A.
