Python NumPy 的 transpose() 方法如何置换数组的轴?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32034237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does NumPy's transpose() method permute the axes of an array?
提问by Frank Hu
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]]])
When we pass a tuple of integers to the transpose()
function, what happens?
当我们将整数元组传递给transpose()
函数时,会发生什么?
To be specific, this is a 3D array: how does NumPy transform the array when I pass the tuple of axes (1, 0 ,2)
? Can you explain which row or column these integers refer to? And what are axis numbers in the context of NumPy?
具体来说,这是一个 3D 数组:当我传递轴元组时,NumPy 如何转换数组(1, 0 ,2)
?你能解释一下这些整数指的是哪一行或哪一列吗?NumPy 上下文中的轴号是什么?
采纳答案by Alex Riley
To transpose an array, NumPy just swaps the shape and stride information for each axis. Here are the strides:
为了转置数组,NumPy 只是交换每个轴的形状和步幅信息。以下是步骤:
>>> arr.strides
(64, 32, 8)
>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)
Notice that the transpose operation swapped the strides for axis 0 and axis 1. The lengths of these axes were also swapped (both lengths are 2
in this example).
请注意,转置操作交换了轴 0 和轴 1 的步幅。这些轴的长度也交换了(2
在本示例中为两个长度)。
No data needs to be copied for this to happen; NumPy can simply change how it looks at the underlying memory to construct the new array.
无需复制数据即可实现此目的;NumPy 可以简单地改变它对底层内存的看法来构造新数组。
Visualising strides
可视化步幅
The stride value represents the number of bytes that must be travelled in memory in order to reach the next value of an axis of an array.
stride 值表示必须在内存中移动的字节数,以便到达数组轴的下一个值。
Now, our 3D array arr
looks this (with labelled axes):
现在,我们的 3D 数组arr
看起来像这样(带有标记的轴):
This array is stored in a contiguous block of memory; essentially it is one-dimensional. To interpret it as a 3D object, NumPy must jump over a certain constant number of bytes in order to move along one of the three axes:
这个数组存储在一个连续的内存块中;本质上它是一维的。要将其解释为 3D 对象,NumPy 必须跳过一定数量的字节才能沿三个轴之一移动:
Since each integer takes up 8 bytes of memory (we're using the int64 dtype), the stride value for each dimension is 8 times the number of values that we need to jump. For instance, to move along axis 1, four values (32 bytes) are jumped, and to move along axis 0, eight values (64 bytes) need to be jumped.
由于每个整数占用 8 个字节的内存(我们使用的是 int64 dtype),因此每个维度的步幅值是我们需要跳转的值数量的 8 倍。例如,沿轴 1 移动,需要跳转四个值(32 个字节),沿轴 0 移动,需要跳转八个值(64 个字节)。
When we write arr.transpose(1, 0, 2)
we are swapping axes 0 and 1. The transposed array looks like this:
当我们写入时,arr.transpose(1, 0, 2)
我们正在交换轴 0 和 1。转置数组如下所示:
All that NumPy needs to do is to swap the stride information for axis 0 and axis 1 (axis 2 is unchanged). Now we must jump further to move along axis 1 than axis 0:
NumPy 需要做的就是交换轴 0 和轴 1 的步幅信息(轴 2 不变)。现在我们必须跳得更远才能沿轴 1 移动而不是沿轴 0:
This basic concept works for any permutation of an array's axes. The actual code that handles the transpose is written in C and can be found here.
这个基本概念适用于数组轴的任何排列。处理转置的实际代码是用 C 编写的,可以在这里找到。
回答by Falko
As explained in the documentation:
如文档中所述:
By default, reverse the dimensions, otherwise permute the axes according to the values given.
默认情况下,反转维度,否则根据给定的值排列轴。
So you can pass an optional parameter axes
defining the new order of dimensions.
因此,您可以传递axes
定义新维度顺序的可选参数。
E.g. transposing the first two dimensions of an RGB VGA pixel array:
例如,转置 RGB VGA 像素阵列的前两个维度:
>>> x = np.ones((480, 640, 3))
>>> np.transpose(x, (1, 0, 2)).shape
(640, 480, 3)
回答by Raghu Ram
To summarise a.transpose()[i,j,k] = a[k,j,i]
总结一下a.transpose()[i,j,k] = a[k,j,i]
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.
when is a tuple parameter is passed axes are permuted according to the tuple. For example
当传递元组参数时,轴会根据元组进行排列。例如
a = np.array( range(24), int).reshape((2,3,4))
a = np.array( range(24), int).reshape((2,3,4))
a[i,j,k] equals a.transpose((2,0,1))[k,i,j]
a[i,j,k] 等于 a.transpose((2,0,1))[k,i,j]
axis 0 takes 2nd place
轴 0 排在第二位
axis 1 takes 3rd place
轴 1 排在第三位
axis 2 tales 1st place
轴 2 故事第一名
of course we need to take care that values in tuple parameter passed to transpose are unique and in range(number of axis)
当然,我们需要注意传递给 transpose 的元组参数中的值是唯一的并且在范围内(轴数)
回答by Robert B
In C notation, your array would be:
在 C 符号中,您的数组将是:
int arr[2][2][4]
which is an 3D array having 2 2D arrays. Each of those 2D arrays has 2 1D array, each of those 1D arrays has 4 elements.
这是一个具有 2 个 2D 阵列的 3D 阵列。每个二维数组都有 2 个一维数组,每个一维数组都有 4 个元素。
So you have three dimensions. The axes are 0, 1, 2, with sizes 2, 2, 4. This is exactly how numpy treats the axes of an N-dimensional array.
所以你有三个维度。轴为 0、1、2,大小为 2、2、4。这正是 numpy 处理 N 维数组轴的方式。
So, arr.transpose((1, 0, 2))
would take axis 1 and put it in position 0, axis 0 and put it in position 1, and axis 2 and leave it in position 2. You are effectively permuting the axes:
因此,arr.transpose((1, 0, 2))
将轴 1 置于位置 0,轴 0 置于位置 1,轴 2 并将其置于位置 2。您实际上是在排列轴:
0 -\/-> 0
1 -/\-> 1
2 ----> 2
In other words, 1 -> 0, 0 -> 1, 2 -> 2
. The destination axes are always in order, so all you need is to specify the source axes. Read off the tuple in that order: (1, 0, 2)
.
换句话说,1 -> 0, 0 -> 1, 2 -> 2
。目标轴始终按顺序排列,因此您只需指定源轴即可。按以下顺序读取元组:(1, 0, 2)
.
In this case your new array dimensions are again [2][2][4]
, only because axes 0 and 1 had the same size (2).
在这种情况下,您的新数组维度再次为[2][2][4]
,仅因为轴 0 和 1 具有相同的大小 (2)。
More interesting is a transpose by (2, 1, 0)
which gives you an array of [4][2][2]
.
更有趣的是转置,(2, 1, 0)
它为您提供了一个[4][2][2]
.
0 -\ /--> 0
1 --X---> 1
2 -/ \--> 2
In other words, 2 -> 0, 1 -> 1, 0 -> 2
. Read off the tuple in that order: (2, 1, 0)
.
换句话说,2 -> 0, 1 -> 1, 0 -> 2
。按以下顺序读取元组:(2, 1, 0)
.
>>> arr.transpose((2,1,0))
array([[[ 0, 8],
[ 4, 12]],
[[ 1, 9],
[ 5, 13]],
[[ 2, 10],
[ 6, 14]],
[[ 3, 11],
[ 7, 15]]])
You ended up with an int[4][2][2]
.
你最终得到了一个int[4][2][2]
.
You'll probably get better understanding if all dimensions were of different size, so you could see where each axis went.
如果所有维度的大小不同,您可能会更好地理解,这样您就可以看到每个轴的去向。
Why is the first inner element [0, 8]
? Because if you visualize your 3D array as two sheets of paper, 0
and 8
are lined up, one on one paper and one on the other paper, both in the upper left. By transposing (2, 1, 0)
you're saying that you want the direction of paper-to-paper to now march along the paper from left to right, and the direction of left to right to now go from paper to paper. You had 4 elements going from left to right, so now you have four pieces of paper instead. And you had 2 papers, so now you have 2 elements going from left to right.
为什么是第一个内部元素[0, 8]
?因为如果你把你的 3D 阵列想象成两张纸,0
并8
排成一行,一张在一张纸上,一张在另一张纸上,都在左上角。通过转置,(2, 1, 0)
您是说您希望纸到纸的方向现在从左到右沿着纸行进,而从左到右的方向现在从纸到纸。你有 4 个元素从左到右,所以现在你有四张纸。你有 2 篇论文,所以现在你有 2 个元素从左到右。
Sorry for the terrible ASCII art. ˉ\_(ツ)_/ˉ
抱歉糟糕的 ASCII 艺术。 ˉ\_(ツ)_/ˉ
回答by Ay?e Nur
It seems the question and the example originates from the book Python for Data Analysisby Wes McKinney. This feature of transpose
is mentioned in Chapter 4.1. Transposing Arrays and Swapping Axes.
似乎问题和示例源自Wes McKinney的《Python for Data Analysis》一书。这个特性transpose
在第 4.1 章中提到。转置数组和交换轴。
For higher dimensional arrays,
transpose
will accept a tuple of axis numbers to permute the axes (for extra mind bending).
对于更高维的数组,
transpose
将接受一个轴号元组来排列轴(为了额外的头脑弯曲)。
Here "permute" means "rearrange", so rearranging the order of axes.
这里“置换”的意思是“重新排列”,因此重新排列轴的顺序。
The numbers in .transpose(1, 0, 2)
determines how the order of axes are changed compared to the original. By using .transpose(1, 0, 2)
, we mean, "Change the 1st axe with the 2nd." If we use .transpose(0, 1, 2)
, the array will stay the same because there is nothing to change; it is the default order.
中的数字.transpose(1, 0, 2)
确定与原始轴的顺序相比如何更改。使用.transpose(1, 0, 2)
,我们的意思是“用第二把斧头换掉第一把斧子”。如果我们使用.transpose(0, 1, 2)
,数组将保持不变,因为没有任何变化;这是默认顺序。
The example in the book with a (2, 2, 4)
sized array is not very clear since 1st and 2nd axes has the same size. So the end result doesn't seem to change except the reordering of rows arr[0, 1]
and arr[1, 0]
.
书中带有(2, 2, 4)
大小数组的示例不是很清楚,因为第 1 轴和第 2 轴具有相同的大小。因此,除了重新排列行arr[0, 1]
和arr[1, 0]
.
If we try a different example with a 3 dimensional array with each dimension having a different size, the rearrangement part becomes more clear.
如果我们尝试使用每个维度具有不同大小的 3 维数组的不同示例,则重排部分会变得更加清晰。
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]]])
Here, original array sizes are (2, 3, 4)
. We changed the 1st and 2nd, so it becomes (3, 2, 4)
in size. If we look closer to see how the rearrangement exactly happened; arrays of numbers seems to have changed in a particular pattern. Using the paper analogy of @RobertB, if we were to take the 2 chunks of numbers, and write each one on sheets, then take one row from each sheet to construct one dimension of the array, we would now have a 3x2x4-sized array, counting from the outermost to the innermost layer.
这里,原始数组大小为(2, 3, 4)
. 我们改变了第 1 个和第 2 个,所以它变成(3, 2, 4)
了大小。如果我们仔细观察重排究竟是如何发生的;数字数组似乎以特定模式发生了变化。使用@ RobertB的纸上类比,如果我们取 2 个数字块,并将每个数字写在纸上,然后从每张纸中取出一行来构造数组的一个维度,我们现在将拥有一个 3x2x4 大小的数组,从最外层到最内层。
[ 0, 1, 2, 3] \ [12, 13, 14, 15]
[ 4, 5, 6, 7] \ [16, 17, 18, 19]
[ 8, 9, 10, 11] \ [20, 21, 22, 23]
It could be a good idea to play with different sized arrays, and change different axes to gain a better intuition of how it works.
使用不同大小的数组并更改不同的轴以更好地了解其工作原理可能是个好主意。