aopstudio 的个人博客

记录精彩的程序人生

AOP=art of programming=编程的艺术=程艺
  menu
41 文章
0 浏览
8 当前访客
ღゝ◡╹)ノ❤️

深入理解 NumPy 中的 `axis`:维度、形状与操作的逻辑

在使用 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 中,你可以通过数组的属性直接访问 ndimshape

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 函数根据对 ndimshape 的影响分为几类。

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 排序与变换函数:不改变 ndimshape

这类函数(如 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 方向上进行,只是重新排列元素。
  • 结果ndimshape 均不变。

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 的核心逻辑是:

你沿着哪个轴操作,哪个轴就会被“处理”或“压缩”

理解 ndimshape 的区别,掌握不同函数对维度的影响,是熟练使用 NumPy 的基石。记住:使用 arr.ndimarr.shape 可以随时查看数组的维度和形状,这是分析任何数组操作的基础。下次当你面对 axis=0axis=1 时,不妨先打印一下 arr.shape,再问自己:“这个操作会压缩哪个维度?” 答案往往就清晰了。

作者:aopstudio撰写大纲和初稿,Qwen润色并补充
发布时间:2025年8月18日
如有帮助,欢迎点赞、收藏、分享!


标题:深入理解 NumPy 中的 `axis`:维度、形状与操作的逻辑
作者:aopstudio
地址:https://neusoftware.top/articles/2025/08/18/1755505289264.html