NumPy

在数学中,将矩阵的行列互换就称之为转置。那在NumPy数组中也是如此。
NumPy共有三种转置方式**T属性**、transpose方法swapaxes方法

T属性

T属性 它比较常用于二维数组,通过行列互换得到一个新的数组,和数学中的转置是一模一样的。

通过转置后得到一个行列互换的新的矩阵:

In [170]: arr = np.arange(12).reshape(4,3)

In [171]: arr
Out[171]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

In [172]: arr.T
Out[172]:
array([[ 0,  3,  6,  9],
       [ 1,  4,  7, 10],
       [ 2,  5,  8, 11]])

比较好奇如果在三维数组中通过T属性来转置会发生什么

In [167]: arr = np.arange(24).reshape((3, 2, 4))

In [168]: arr
Out[168]:
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

In [169]: arr.T
Out[169]:
array([[[ 0,  8, 16],     
        [ 4, 12, 20]],

       [[ 1,  9, 17],
        [ 5, 13, 21]],

       [[ 2, 10, 18],
        [ 6, 14, 22]],

       [[ 3, 11, 19],
        [ 7, 15, 23]]])

可以看到三维数组也是可以转置的。值得注意的是它的转置和二维数组的转置有明显的不同。
这里我是这么理解的:
原数组arr中,0的索引arr[0,0,0](接下来简写为[0,0,0]这种格式)。经过转置后它的索引为[0,0,0]
接下来看1的索引[0,0,1],经过转置后变成了[1,0,0],这样就很好理解了。
再看10的索引[1,0,2],经过转置后变成了[2,0,1]
到这步相信已经解释的再清楚不过了。

那我们回过头来再看下二维数组

In [171]: arr
Out[171]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

In [172]: arr.T
Out[172]:
array([[ 0,  3,  6,  9],
       [ 1,  4,  7, 10],
       [ 2,  5,  8, 11]])

原数组arr中,0的索引arr[0,0]。经过转置后它的索引为[0,0]
接下来看1的索引[0,1],经过转置后变成了[1,0],这样就很好理解了。
再看10的索引[3,1],经过转置后变成了[1,3]

所谓的转置其实就是把该元素的索引做了个倒转而已,非常简单。

transpose方法

transposeT的玩法有点差别,它的参数是数组的轴序列,通过改变轴的顺序从而导致数组中各元素索引的改变。
如果对轴不是很了解,可以参考这篇文章
关于NumPy数组的轴

In [196]: arr = np.arange(16).reshape((2, 2, 4))

In [197]: arr     # arr 原本的轴序列为(0, 1, 2)
Out[197]:
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])

In [199]: arr.transpose((1, 0, 2)) # 参数中,我们把轴的顺序改成了(1, 0, 2)
Out[199]:
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

在这里我们把轴的顺序由原本的(0, 1, 2)改成了(1, 0, 2)。也就是把前两位互换了位置,请牢记这句话。

接下来还是按照T属性的原理:
元素4转置前的索引值为(0, 1, 0),现在要把前两位互换下位置变成(1, 0, 0) , 也就变成了上图中的效果。
元素10转置前的索引值为(1, 0, 2),经过互换后变成了 (0, 1, 2),如上图。

如果我把三个轴的位置都更改了,那会发生什么?
再看下面这个案例

In [210]: arr.transpose((2,0,1))
Out[210]:
array([[[ 0,  4],
        [ 8, 12]],

       [[ 1,  5],
        [ 9, 13]],

       [[ 2,  6],
        [10, 14]],

       [[ 3,  7],
        [11, 15]]])

轴的顺序由原来的(0, 1, 2)变成了(2, 0, 1),三个位置都发生了改变。
我们结合上面的代码来分析下:
元素4从原本的(0, 1, 0)变成了(0, 0, 1)
元素10从原本的(1, 0, 2)变成了(2, 1, 0)

这里稍微总结下,transposeT属性最大的区别在于,后者是把各元素的索引序列从左往右全部翻转过来。而前者则可以很灵活的去控制想要转置的元素,在多维数组中优势会更加明显。

swapaxes方法

核心用法与transpose差不多,只是参数发生了变化。
arr.swapaxes(1, 2),这段代码的意思是将第一个轴与第二个轴进行交换。也就等同于将轴的顺序由(0, 1, 2) 变成了(0, 2, 1)
接下来的索引的专置和transpose是一样的,这里就略过了。

In [218]: arr.swapaxes(1, 2)
Out[217]:
array([[[ 0,  4],
        [ 1,  5],
        [ 2,  6],
        [ 3,  7]],

       [[ 8, 12],
        [ 9, 13],
        [10, 14],
        [11, 15]]])

等同于

In [218]: arr.transpose((0, 2, 1))
Out[218]:
array([[[ 0,  4],
        [ 1,  5],
        [ 2,  6],
        [ 3,  7]],

       [[ 8, 12],
        [ 9, 13],
        [10, 14],
        [11, 15]]])

总结

本章学习了数组的转置与轴对换的内容,NumPy共有三种转置方式**T属性**、transpose方法swapaxes方法
T属性: 比较简单粗暴,直接将数组的轴序从左往右翻转且只有这一种方式。例如某个元素在数组中的索引为(1,0,2),经过T属性的转置后它的索引将变成(2, 0, 1),核心原理与数学的转置相同。

transpose方法 : 它的参数为轴的序列,你可以通过打乱轴的排序来转置数组。例如arr.transpose((0, 2, 1)),数组的轴序由原来的(0, 1, 2)变成了(0, 2, 1),从而导致元素N的索引由原来的(a, b, c)变成了(a, c, b)

swapaxes方法: 它的核心原理与transpose相同,唯一的区别是它的参数不是整个轴的序列,而是指定2个轴然后进行互换。例如swapaxes(1, 2),这段代码的意思就是轴1与轴2互换,也就是将轴序换成了(0, 2, 1),就这个区别。