python numpy中axis的含义_Numpy中的axis/axes详解

本文详细解释了在Numpy中,axis的概念及其与dimensions和rank的关系。通过实例展示了如何使用axis来索引和操作多维数组,包括求和、排序等操作,强调了axis在不同维度数据处理中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,在Numpy中,维数(dimensions)通过轴(axes)来扩展,轴的个数被称作rank。这里的rank不是线性代数中的rank(秩),它指代的依旧是维数(number of dimensions):

The number of axes (dimensions) of the array. In the Python world, the number of dimensions is referred to as rank.

在数学或者物理的概念中,dimensions被认为是在空间中表示一个点所需要的最少坐标个数,但是在Numpy中,dimensions指代的是axes。也就是说,axes、dimensions、rank这几个概念是相通的。

下面举例子,比如我们在3-D空间中定义三个点,用array的形式表达:

>>>import numpy as np

>>>a = np.array([[1,2,3],[2,3,4],[3,4,9]])

>>>a

array([[1, 2, 3],

[2, 3, 4],

[3, 4, 9]])

按照以往的理解,我们可能会认为这个array是三维的,但实际上在Numpy中,这个array的dimensions,也就是rank的值是等于2的:

>>>np.ndim(a)

2

因为它只有两个axis,只不过这两个axis的长度(length)均为3:

>>>np.shape(a)

(3, 3)

同时,这个矩阵在线性代数中的rank(秩)依旧是3(这里要加以区分):

>>>np.linalg.matrix_rank(a)

3

也就是说,在Numpy中,任何vector都被看作具有不同长度(length)的一维array。

下面继续聊聊axis/axes,我们依旧先定义一个3-D的array:

>>>b = np.array([[[1,2,3,4],[1,3,4,5]],[[2,4,7,5],[8,4,3,5]],[[2,5,7,3],[1,5,3,7]]])

>>>b

array([[[1, 2, 3, 4],

[1, 3, 4, 5]],

[[2, 4, 7, 5],

[8, 4, 3, 5]],

[[2, 5, 7, 3],

[1, 5, 3, 7]]])

>>>b.shape

(3, 2, 4)

我们定义了一个shape为(3, 2, 4)的array,这个shape(用tuple表示)可以理解为在每个轴(axis)上的size,也即占有的长度(length),三个值的含义:axis = 0对应轴上的元素length = 3,axis = 1对应轴上的元素length = 2,axis = 2对应轴上的元素length = 4,也就是说,当我们在array中选定某个元素时,可能用到的最大索引(index)范围,举例:

>>>b[1]

array([[2, 4, 7, 5],

[8, 4, 3, 5]])

>>>b[1,:,:] # Equivalent value

array([[2, 4, 7, 5],

[8, 4, 3, 5]])

这里的b[1]和b[1, :, :]表示在axis = 0的轴上选取第一个元素,同时选取axis = 1和axis = 2上的全部元素。我们可以暂时把多个axes想象成多层layers,当然也可以想象成树结构,虽然这么说并不准确,但是为了方便想象可以暂时这么理解:

axis = 0表示第一层layer:在代码中看到的效果就是b从外向里数第一层 [ ],对应的元素(length = 3)就是第一层 [ ] 中用逗号分隔的全部元素(注意:不要关注第二层及以上 [ ] 里的逗号),很明显这一层的元素数目为3;同理,axis = 1表示第二层layer:第一层layer中用逗号分隔开的任意一个 [ ] 中,再由逗号分隔开的全部元素(length = 2);axis = 2同理,表示最后一层layer中的元素(length = 4)。这么说还是有些乱,我把刚才的array重新布置一下:

5637cb7b710de02f61d7b3e7752ed0d0.png

像这样用猿们写c/c++代码时候的风格排布下,黑色代表第一层layer,可以看到有三个元素,红色代表第二层layer,在第一层layer相同的前提下有两个元素,蓝色代表第三层layer,在第一层和第二层layer都相同的前提下有4个元素。这样也就对应上了b.shape = (3, 2, 4)的结果。

这时候如果我们想定位到元素8应该怎么索引?可以看到8在第一层layer的第二个元素内,同时在第二层layer的第二个元素内、第三层layer的第一个元素,也就是说:8是axis = 0轴上的第二个位置、axis = 1轴上的第二个位置,axis = 2的第一个位置共同retrieve到的元素。写成代码:

>>>b[1,1,0]

8

噔噔噔~就酱。同时也可以发现,array有几维,我们就可以用几个integer去索引到(index)它的元素。

进一步看下,对于b这个array来说,最后一个元素对应的位置就是可以用到的最大index(从0开始):

>>>b[2,1,3]

7

任一axis上再大一点就会出现IndexError了:

>>>b[2,1,4]

Traceback (most recent call last):

File "", line 1, in

b[2,1,4]

IndexError: index 4 is out of bounds for axis 2 with size 4

之所以要设置不同的axis,是因为对于数据我们可以进行不同维度的处理。例如现在我们收集了四个同学对苹果、榴莲、西瓜这三种水果的喜爱程度进行打分的数据(总分为10),每个同学都有三个特征:

>>>item = np.array([[1,4,8],[2,3,5],[2,5,1],[1,10,7]])

>>>item

array([[1, 4, 8],

[2, 3, 5],

[2, 5, 1],

[1, 10, 7]])

每一行包含了同一个人的三个特征,如果我们想看看哪个同学最喜欢吃水果,那就可以用:

>>>item.sum(axis = 1)

array([13, 10, 8, 18])

可以大概看出来同学4最喜欢吃水果。

如果我们想看看哪种水果最受欢迎,那就可以用:

>>>item.sum(axis = 0)

array([ 6, 22, 21])

可以看出基本是榴莲最受欢迎~~~耶~~~咳、这就是axis存在的意义- -、为了方便地从不同角度对数据进行处理。

接下来我们将对更高维度的array进行计算,会用到提供axis这个parameter的一些函数对轴这个概念进一步说明:

依旧是求和:ndarray.sum(axis=None, dtype=None, out=None, keepdims=False),等价于numpy.sum(a, axis=None, dtype=None, out=None, keepdims=False):

>>>b.sum()

94

>>>b.sum(axis = 0)

array([[ 5, 11, 17, 12],

[10, 12, 10, 17]])

>>>b.sum(axis = 1)

array([[ 2, 5, 7, 9],

[10, 8, 10, 10],

[ 3, 10, 10, 10]])

>>>b.sum(axis = 2)

array([[10, 13],

[18, 20],

[17, 16]])

不设置axis的时候,sum返回所有元素的加和;当指定axis时,意味着对某一轴内的所有元素对应求和,同时这一层layer就collapsed掉了,因为这个过程是一个reduction operation。例如求b.sum(axis = 1)时,我们还是回到这个图:

c490e4a571346b2cae26769ac24e3872.png

axis = 1,直观上看,意味着我们需要关注红色layer之间的元素,顺次对axis = 0、axis = 2这两个轴上相同位置的不同红框之间的元素求和(好拗口),也就是下图中连线的元素对应求和:

caf43fb133436c5d0b6758e2862dc59d.png

可以得到(非规范写法):

array([

[ 2, 5, 7, 9],

[10, 8, 10, 10],

[ 3, 10, 10, 10]

])

也就是说,假设求和后的array为b_sum,就有:

b_sum[0, 0] = b[0, 0, 0]+b[0, 1, 0]; b_sum[0, 1] = b[0, 0, 1]+b[0, 1, 1]; b_sum[0, 2] = b[0, 0, 2]+b[0, 1, 2]; b_sum[0, 3] = b[0, 0, 3]+b[0, 1, 3];

b_sum[1, 0] = b[1, 0, 0]+b[1, 1, 0]; b_sum[1, 1] = b[1, 0, 1]+b[1, 1, 1]; b_sum[1, 2] = b[1, 0, 2]+b[1, 1, 2]; b_sum[1, 3] = b[1, 0, 3]+b[1, 1, 3];

b_sum[2, 0] = b[2, 0, 0]+b[2, 1, 0]; b_sum[2, 1] = b[2, 0, 1]+b[2, 1, 1]; b_sum[2, 2] = b[2, 0, 2]+b[2, 1, 2]; b_sum[2, 3] = b[2, 0, 3]+b[2, 1, 3];

即在axis = 0、axis = 2相同的情况下,对axis = 1上的全部元素进行求和所得的结果。

同时,在对这个轴上的元素求和之后,这个axis就消失了,我们可以再检查一下求和后的shape:

>>>b.sum(axis = 1).shape

(3, 4)

可以看到,对axis = 1上的元素进行求和后的shape由原来的(3, 2, 4)坍塌到(3, 4),其他轴可以自行验证。

接下来再看排序函数:ndarray.sort(axis=-1, kind='quicksort', order=None),也可以用numpy.sort(a, axis=-1, kind='quicksort', order=None),但是前者会改变b后者不会改变b:

>>>np.sort(b)

array([[[1, 2, 3, 4],

[1, 3, 4, 5]],

[[2, 4, 5, 7],

[3, 4, 5, 8]],

[[2, 3, 5, 7],

[1, 3, 5, 7]]])

>>>np.sort(b, axis = 0)

array([[[1, 2, 3, 3],

[1, 3, 3, 5]],

[[2, 4, 7, 4],

[1, 4, 3, 5]],

[[2, 5, 7, 5],

[8, 5, 4, 7]]])

>>>np.sort(b, axis = 1)

array([[[1, 2, 3, 4],

[1, 3, 4, 5]],

[[2, 4, 3, 5],

[8, 4, 7, 5]],

[[1, 5, 3, 3],

[2, 5, 7, 7]]])

第一种情况,sort默认的axis值为-1,对于我们这个case来说,相当于对axis = 2轴上的元素进行排序(也就是倒数第一个轴)。

还是拿其中一种情况举例子,对于axis = 0,先直观来看,我们需要关注黑色框之间对应的元素:

40ff0218d1f194ded0c1382dc88a598c.png

我只标注出来了在轴axis = 0上进行排序的过程中,第一组元素之间和最后一组元素之间的对应关系,其他组元素同理。

从索引的角度也可以表示:

对b[0, 0, 0]、b[1, 0, 0]、b[2, 0, 0]进行排序,并将结果由小到大重新排列;

对b[0, 0, 1]、b[1, 0, 1]、b[2, 0, 1]进行排序,并将结果由小到大重新排列;

对b[0, 0, 2]、b[1, 0, 2]、b[2, 0, 2]进行排序,并将结果由小到大重新排列;

对b[0, 0, 3]、b[1, 0, 3]、b[2, 0, 3]进行排序,并将结果由小到大重新排列;

对b[0, 1, 0]、b[1, 1, 0]、b[2, 1, 0]进行排序,并将结果由小到大重新排列;

其余同理……

嗯就先举这两个例子吧,其他带有参数axis的函数也可以从这两个角度去分析。

原文链接:https://blog.csdn.net/W_H_M_2018/article/details/105536728

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值