数组的转置和轴对称
数组的转置指的是将数组中的每个元素按照一定的规则进行位置变换。NumPy提供了transpose()方法和T属性两种实现形式。其中,简单的转置可以使用T属性,它其实就是进行轴对换而已。例如,现在有个3行4列的二维数组,那么使用T属性对数组转置后,形成的是一个4行3列的新数组,示例代码如下。
In [79]: arr = np.arange(12).reshape(3, 4)
In [80]: arr
Out[80]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [81]: arr.T # 使用T属性对数组进行转置
Out[81]:
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
对于高纬度的数组而言,transpose()方法需要得到一个由轴编号组成的元组,才能对这些轴进行转置。假设现在有个数组arr,具体代码如下:
In [82]: arr = np.arange(16).reshape((2, 2, 4))
In [83]: arr
Out[83]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [84]: arr.shape
Out[84]: (2, 2, 4)
上述数组arr的shape是(2,2,4),表示是一个三维数组,也就是说有三个轴,每个轴都对应着一个编号,分别为0、1、2。
如果希望对arr进行转置操作,就需要对它的shape中的顺序进行调换。也就是说,当使用transpose()方法对数组的shape进行调换时,需要以元组的形式传入shape的编号,比如(1,0,2)。如果调用transpose()方法时传入“(0,1,2)”,则数组的shape不会发生任何变化。
下面是arr调用transpose(1,0,2)的示例,具体代码如下。
In [85]: arr.transpose(1, 2, 0) # 使用transpose()方法对数组进行转置
Out[85]:
array([[[ 0, 8],
[ 1, 9],
[ 2, 10],
[ 3, 11]],
[[ 4, 12],
[ 5, 13],
[ 6, 14],
[ 7, 15]]])
如果我们不输入任何参数,直接调用transpose()方法,则其执行的效果就是将数组进行转置,作用等价于transpose(2,1,0)。接下来,通过一张图比较使用所述两种方式的转置操作,具体如图1所示。
图1 transpose()方法传参对比
在某些情况下,我们可能只需要转换其中的两个轴,这时我们可以使用ndarray提供的swapaxes()方法实现,该方法需要接受一对轴编号,示例代码如下。
In [86]: arr
Out[86]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [87]: arr.swapaxes(1, 0) # 使用swapaxes方法对数组进行转置
Out[87]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
多学一招:轴编号
在NumPy中维度(dimensions)叫做轴(axes),轴的个数叫做秩(rank)。例如,3D空间中有个点的坐标[1, 2, 1]是一个秩为1的数组,因为它只有一个轴。这个轴有3个元素,所以我们说它的长度为3。
在下面的示例中,数组有2个轴,第一个轴的长度为2,第二个轴的长度为3。
array([[ 1., 0., 0.],
[ 0., 1., 2.]])
高维数据执行某些操作(如转置)时,需要指定维度编号,这个编号是从0开始的,然后依次递增1。其中,位于纵向的轴(y轴)的编号为0,位于横向的轴(x轴)的编号为1,以此类推。
维度编号示意图如图2所示。
图2 维度编号图示