坦白来说,NumPy轴是NumPy系统中最难理解的事情之一。如果您刚刚开始使用NumPy,则尤其如此。许多初学者都很难理解NumPy轴的工作原理。

Numpy axes类似于在坐标系中的轴

当你第一次学习图形时,回想一下早期的数学。您了解了笛卡尔坐标。
NumPy轴与笛卡尔坐标系中的轴非常相似。

类比:笛卡尔坐标系坐标轴

简单的二维笛卡尔坐标系具有两个轴,即x轴和y轴。这些轴基本上只是笛卡尔空间中的方向(正交方向)。此外,我们可以通过它沿每个轴的位置来识别笛卡尔空间中点的位置。
image.png

NUMPY 的轴是行和列的方向

就像坐标系一样,Numpy阵列也有轴。
image.png
在二维NumPy数组中,轴是沿行和列的方向。

axis 0是沿着行的方向。

假设我们讨论的是多维数组,那么轴0就是向下行的轴。
image.png
⚠️请记住,这确实适用于二维数组和多维数组。一维数组是一个特例,我将在本教程的后面解释。

**axis 1**是沿着列的方向。

在多维NumPy阵列中,axis1是第2轴。当我们谈论二维和多维数组时,axis1是横跨列水平延伸的轴。
image.png
⚠️再一次,请记住,一维数组的工作方式略有不同。

Numpy数组轴编号

在这一点上可能很明显,但我应该指出NumPy中的数组轴是编号的,重要的是,它们从0开始编号。
这就像Python序列的索引值一样。在Python序列中 - 如列表和元组 - 序列中的值具有与之关联的索引。
所以,假设我们有一个带有几个大写字母的Python列表:

  1. alpha_list = ['A','B','C','D']

如果我们检索第一个项目的索引值(’A’)

  1. alpha_list.index('A')

我们发现’A’位于索引位置0。这里,A是列表中的第一项,但索引位置为0。
基本上所有的Python序列都是这样的。在任何Python序列中 - 如列表,元组或字符串 - 索引从0开始。
NumPy轴的编号基本上以相同的方式工作。它们从0开始编号。因此“第一”轴实际上是“axis0”。“第二”轴是“axis1”,依此类推。

Numpy轴在函数中的应用

Numpy sum

在尝试理解NumPy sum中的axis时,您需要知道axis参数实际控制的是什么。
在np.sum()中,axis参数控制将聚合哪个轴。换句话说,axis参数控制哪个轴将被折叠
请记住,sum(),mean(),min(),median()和其他统计函数等函数会聚合您的数据。
为了解释“聚合”的含义,我将举一个简单的例子:想象一下,你有一组5个数字。如果总结这5个数字,结果将是一个数字。求和有效地汇总了您的数据。它将大量的值折叠为单个值。

类似地,当您在带有axis参数的二维数组上使用np.sum()时,它会将二维数组折叠为一维数组。它会折叠数据减少维度

但哪个轴会被折叠?将NumPy和函数与axis参数一起使用时,指定的轴是折叠的轴

numpy sum with axis = 0

在这里,我们将使用轴= 0的Numpy和函数。
创建一个简单的NumPy数组。

  1. np_array_2d = np.arange(0, 6).reshape([2,3])
  2. print(np_array_2d)
  3. [[0 1 2]
  4. [3 4 5]]

接下来,让我们使用axis= 0的Numpy求和函数sum。

  1. np.sum(np_array_2d, axis = 0)
  2. # 输出:array([3, 5, 7])


当我们设置axis = 0时,该函数实际上对列进行求和**。结果是一个新的NumPy数组,其中包含每列的总和。为什么?轴0不是指行吗?
这让许多初学者感到困惑,所以让我解释一下。正如我之前提到的,axis参数指示哪个轴折叠。
image.png
因此,当我们设置axis = 0时,我们不会对行进行求和。当我们设置axis = 0时,我们正在聚合数据,以便我们折叠行……我们将轴0折叠。

numpy sum with axis = 1
  1. print(np_array_2d)
  2. [[0 1 2]
  3. [3 4 5]]
  4. np.sum(np_array_2d, axis = 1)
  5. array([3, 12])

同样,使用sum()函数,axis参数设置在求和过程中折叠的轴。
image.png
代码具有跨列求和的效果。它折叠了axis1。

Numpy concatenate

现在让我们来看一个不同的例子。在这里,我们将在使用Numpy连接函数(np.concatenate())的上下文中使用axis参数。
当我们将axis参数与np.concatenate()函数一起使用时,axis参数定义了我们堆叠数组的轴。
看例子:

  1. np_array_1s = np.array([[1,1,1],[1,1,1]])
  2. np_array_9s = np.array([[9,9,9],[9,9,9]])
  3. array([[1, 1, 1],
  4. [1, 1, 1]])
  5. array([[9, 9, 9],
  6. [9, 9, 9]])
  7. #*use NumPy concatenate with axis = 0*
  8. np.concatenate([np_array_1s, np_array_9s], axis = 0)
  9. #输出
  10. array([[1, 1, 1],
  11. [1, 1, 1],
  12. [9, 9, 9],
  13. [9, 9, 9]])

让我们仔细评估语法在这里做了什么。
image.png

  1. #*use NumPy concatenate with axis = 1*
  2. np.concatenate([np_array_1s, np_array_9s], axis = 1)
  3. #输出
  4. array([[1, 1, 1, 9, 9, 9],
  5. [1, 1, 1, 9, 9, 9]])

但是,让我们快速回顾一下这里发生了什么。
image.png

⚠️警告:一维数组的工作方式不同

一维NUMPY数组只有一个轴(即axis=0)
image.png

示例:连接1-D阵列(一维数组)
  1. np_array_1s_1dim = np.array([1,1,1])
  2. np_array_9s_1dim = np.array([9,9,9])
  3. [1 1 1]
  4. [9 9 9]
  5. np.concatenate([np_array_1s_1dim, np_array_9s_1dim], axis = 0)
  6. array([1, 1, 1, 9, 9, 9])

这个输出让许多初学者感到困惑,数组水平连接在一起。
这与函数在二维数组上的工作方式不同。如果我们在二维数组上使用np.concatenate()和axis = 0,则数组将垂直连接在一起。在这种情况下,该功能正常工作。Numpy连接是沿着轴0连接这些数组。问题是在1-d数组中,轴0不像在2维数组中那样指向“向下”

示例:连接1-D阵列时的报错,axis = 1。

  1. np.concatenate([np_array_1s_1dim, np_array_9s_1dim], axis = 1)
  2. IndexError: axis 1 out of bounds [0, 1)

一位数组只有一个轴,axis=0。