How does NumPy's transpose() method permute the axes of an array?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | In [28]: arr = np.arange(16).reshape((2, 2, 4)) In [29]: arr Out[29]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) In [32]: arr.transpose((1, 0, 2)) Out[32]: array([[[ 0, 1, 2, 3], [ 8, 9, 10, 11]], [[ 4, 5, 6, 7], [12, 13, 14, 15]]]) |
当我们将整数元组传递给
具体来说,这是一个3D数组:当我传递轴
为了转置数组,NumPy只需交换每个轴的形状和步幅信息。这是大步前进:
1 2 3 4 5 | >>> arr.strides (64, 32, 8) >>> arr.transpose(1, 0, 2).strides (32, 64, 8) |
请注意,转置操作将轴0和轴1的步幅交换。这些轴的长度也被交换(在此示例中,两个轴的长度均为
无需复制任何数据即可完成此操作; NumPy可以简单地更改其在底层内存中的外观,以构造新的数组。
可视化步幅
跨步值表示为了到达数组轴的下一个值而必须在内存中传输的字节数。
现在,我们的3D数组
该数组存储在连续的内存块中;本质上是一维的。要将其解释为3D对象,NumPy必须跳过一定的恒定字节数才能沿三个轴之一移动:
由于每个整数占用8个字节的内存(我们使用的是int64 dtype),因此每个维度的步幅值是需要跳转的值数的8倍。例如,要沿轴1移动,则要跳过四个值(32字节),而要沿轴0移动,则要跳过八个值(64字节)。
编写
NumPy所需要做的就是交换轴0和轴1的步幅信息(轴2不变)。现在我们必须跳得更远,才能沿着轴1而不是轴0:
这个基本概念适用于数组轴的任何排列。处理转置的实际代码是用C编写的,可以在这里找到。
如文档中所述:
By default, reverse the dimensions, otherwise permute the axes according to the values given.
因此,您可以传递一个可选参数
例如。转置RGB VGA像素阵列的前两个维度:
1 2 3 | >>> x = np.ones((480, 640, 3)) >>> np.transpose(x, (1, 0, 2)).shape (640, 480, 3) |
用C表示法,您的数组将是:
1 | int arr[2][2][4] |
这是具有2个2D阵列的3D阵列。这些2D数组中的每个都有2个1D数组,这些1D数组中的每个都有4个元素。
因此,您具有三个维度。轴为0、1、2,大小为2、2、4。这正是numpy处理N维数组的轴的方式。
因此,
1 2 3 | 0 -\\/-> 0 1 -/\\-> 1 2 ----> 2 |
换句话说,
在这种情况下,仅因为轴0和1具有相同的大小(2),您的新数组尺寸仍然是
更有趣的是
1 2 3 | 0 -\\ /--> 0 1 --X---> 1 2 -/ \\--> 2 |
换句话说,
1 2 3 4 5 6 7 8 9 10 11 12 | >>> arr.transpose((2,1,0)) array([[[ 0, 8], [ 4, 12]], [[ 1, 9], [ 5, 13]], [[ 2, 10], [ 6, 14]], [[ 3, 11], [ 7, 15]]]) |
您以
如果所有尺寸的尺寸都不同,您可能会更好地理解,因此您可以看到每个轴的去向。
为什么第一个内部元素
对不起,可怕的ASCII艺术。
看来问题和示例出自Wes McKinney的《 Python for Data Analysis》一书。
For higher dimensional arrays,
transpose will accept a tuple of axis numbers to permute the axes (for extra mind bending).
这里的"置换"是指"重新排列",因此要重新排列轴的顺序。
书中具有
如果我们尝试使用3维数组(每个维具有不同大小)的不同示例,则重排部分将变得更加清晰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | In [2]: x = np.arange(24).reshape(2, 3, 4) In [3]: x Out[3]: 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 [4]: x.transpose(1, 0, 2) Out[4]: array([[[ 0, 1, 2, 3], [12, 13, 14, 15]], [[ 4, 5, 6, 7], [16, 17, 18, 19]], [[ 8, 9, 10, 11], [20, 21, 22, 23]]]) |
在此,原始数组大小为
1 | [ 0, 1, 2, 3] \\ [12, 13, 14, 15] |
1 | [ 4, 5, 6, 7] \\ [16, 17, 18, 19] |
1 | [ 8, 9, 10, 11] \\ [20, 21, 22, 23] |
最好使用不同大小的数组,并更改不同的轴以更好地了解其工作原理。
总结a.transpose()[i,j,k] = a [k,j,i]
1 2 3 | a = np.array( range(24), int).reshape((2,3,4)) a.shape gives (2,3,4) a.transpose().shape gives (4,3,2) shape tuple is reversed. |
当是元组参数时,将根据元组对轴进行排列。
例如
一个= np.array(range(24),int).reshape((2,3,4))
a [i,j,k]等于a.transpose((2,0,1))[k,i,j]
轴0排名第二
轴1排名第三
轴2故事第一名
当然,我们需要注意传递给转置的元组参数中的值是唯一的,并且在范围(轴数)中