在使用 NumPy 进行数据处理和科学计算时,axis
参数是一个无处不在却又常常令人困惑的概念。无论是求和、拼接、排序还是分割,axis
都在背后决定着操作的方向。理解 axis
的本质,是掌握 NumPy 多维数组操作的关键。
本文将从维度(ndim)、形状(shape) 与 axis
的关系入手,系统梳理 axis
在不同函数中的行为模式,帮助你彻底掌握这一核心概念。
1. 维度(ndim)与形状(shape):两个容易混淆的概念
在深入 axis
之前,我们先明确两个基础但常被混淆的概念:
-
ndim
:表示数组的维度数量(也称为“秩”或“轴数”)。例如:- 标量:
ndim = 0
- 向量:
ndim = 1
- 矩阵:
ndim = 2
- 三维张量:
ndim = 3
- 标量:
-
shape
:表示数组在每个维度上的大小,是一个元组。例如:np.array([1, 2, 3])
的shape
是(3,)
np.array([[1, 2], [3, 4]])
的shape
是(2, 2)
np.random.rand(2, 3, 4)
的shape
是(2, 3, 4)
如何查看 ndim 和 shape?
在 NumPy 中,你可以通过数组的属性直接访问 ndim
和 shape
:
import numpy as np
arr = np.array([[1, 2],
[3, 4]])
print("维度数 (ndim):", arr.ndim) # 输出: 2
print("形状 (shape):", arr.shape) # 输出: (2, 2)
arr.ndim
:直接返回一个整数,表示维度数量。arr.shape
:返回一个元组,表示每个维度的大小。
两者的关系
ndim
改变,shape
一定改变:维度数变了,形状自然不同。shape
改变,ndim
不一定改变:例如,将(2, 3)
的数组 reshape 为(3, 2)
,ndim
仍是 2,但shape
变了。
理解这一点,有助于我们判断一个操作是否“改变了数组的结构”。
2. axis
的含义:操作的“压缩方向”
axis
参数的本质是:指定操作沿着哪个轴进行,而该轴通常会被“压缩”或“折叠”。
以一个二维数组为例:
import numpy as np
arr = np.array([[1, 2],
[3, 4]]) # shape: (2, 2), ndim: 2
axis=0
:沿行方向操作(垂直方向,跨行)。axis=1
:沿列方向操作(水平方向,跨列)。
print(np.sum(arr, axis=0)) # [4 6] -> 沿 axis=0 求和,结果是每列的和
print(np.sum(arr, axis=1)) # [3 7] -> 沿 axis=1 求和,结果是每行的和
注意:结果的 ndim
仍然是 1,但原始数组是 2 维的。这意味着 axis
指定的维度被“压缩”了。
3. 不同函数中 axis
的行为模式
我们可以将 NumPy 函数根据对 ndim
和 shape
的影响分为几类。
3.1 聚合/统计函数:压缩维度(ndim
减少)
这类函数(如 sum
, mean
, max
, argmax
等)会沿指定 axis 进行归约操作,导致该轴被压缩,通常结果的维度数比原数组少 1。
arr = np.array([[1, 2],
[3, 4]])
print(np.max(arr, axis=0)) # [3 4] -> shape: (2,), ndim: 1
print(np.argmax(arr, axis=1)) # [1 1] -> shape: (2,), ndim: 1
- 行为:
axis
对应的维度被“压缩”为 0(即消失)。 - 结果:
ndim
减少 1,shape
改变。
⚠️ 特例:
keepdims=True
参数可以保留被压缩的维度,使其大小为 1:print(np.sum(arr, axis=0, keepdims=True)) # [[4 6]] -> shape: (1, 2), ndim: 2
3.2 数组拼接与分割函数:不改变 ndim
,但改变 shape
这类函数(如 concatenate
, vstack
, hstack
, split
)用于组合或拆分数组,它们不会改变原始数组的维度总数,但会改变整体的 shape
。
arr1 = np.array([[1, 2]])
arr2 = np.array([[3, 4]])
# 沿 axis=0 垂直拼接
result = np.concatenate([arr1, arr2], axis=0)
# result:
# [[1 2]
# [3 4]]
# shape: (2, 2), ndim: 2
# 分割
split_result = np.split(arr, 2, axis=1) # 分成两个 (2,1) 的数组
print([r.shape for r in split_result]) # [(2, 1), (2, 1)]
- 行为:操作沿
axis
进行,但输入和输出的ndim
一致。 - 结果:
ndim
不变,shape
改变。
3.3 排序与变换函数:不改变 ndim
和 shape
这类函数(如 sort
, argsort
, flip
, roll
)是对数组内部元素的重新排列或变换,既不改变维度数,也不改变形状。
arr = np.array([[4, 1],
[3, 2]])
# 沿 axis=1 对每行排序
sorted_arr = np.sort(arr, axis=1)
# sorted_arr:
# [[1 4]
# [2 3]]
print(sorted_arr.shape) # (2, 2)
print(sorted_arr.ndim) # 2
# argsort 返回索引,形状不变
indices = np.argsort(arr, axis=0)
# indices:
# [[1 1]
# [0 0]]
# shape: (2, 2)
- 行为:操作在
axis
方向上进行,只是重新排列元素。 - 结果:
ndim
和shape
均不变。
4. 高维数组中的 axis
:推广到 N 维
axis
的逻辑可以推广到任意维度。例如,一个形状为 (3, 4, 5)
的三维数组:
axis=0
:沿第一个维度(深度)操作,压缩后 shape 变为(4, 5)
axis=1
:沿第二个维度(行)操作,压缩后 shape 变为(3, 5)
axis=2
:沿第三个维度(列)操作,压缩后 shape 变为(3, 4)
arr_3d = np.random.rand(3, 4, 5)
result = np.mean(arr_3d, axis=1) # shape: (3, 5), ndim: 2
5. 总结:一张表掌握 axis
行为
函数类型 | 代表函数 | ndim 是否改变 | shape 是否改变 | axis 含义 |
---|---|---|---|---|
聚合/统计 | sum , max , argmax | ✅ 减少 | ✅ 改变 | 压缩该轴 |
拼接/分割 | concatenate , split , vstack | ❌ 不变 | ✅ 改变 | 沿该轴操作 |
排序/变换 | sort , argsort , flip | ❌ 不变 | ❌ 不变 | 在该轴上重排 |
结语
axis
的核心逻辑是:
你沿着哪个轴操作,哪个轴就会被“处理”或“压缩”。
理解 ndim
和 shape
的区别,掌握不同函数对维度的影响,是熟练使用 NumPy 的基石。记住:使用 arr.ndim
和 arr.shape
可以随时查看数组的维度和形状,这是分析任何数组操作的基础。下次当你面对 axis=0
或 axis=1
时,不妨先打印一下 arr.shape
,再问自己:“这个操作会压缩哪个维度?” 答案往往就清晰了。
作者:aopstudio撰写大纲和初稿,Qwen润色并补充
发布时间:2025年8月18日
如有帮助,欢迎点赞、收藏、分享!
标题:深入理解 NumPy 中的 `axis`:维度、形状与操作的逻辑
作者:aopstudio
地址:https://neusoftware.top/articles/2025/08/18/1755505289264.html