让我们考虑将a
作为一维行/水平数组:
import numpy as np
N = 10
a = np.arange(N) # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a.shape # (10,)
现在我想让b
的一维列/垂直数组转置为a
:
b = a.transpose() # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b.shape # (10,)
但是.transpose()
方法会返回一个完全相同形状的ndarray!
我希望看到的是
np.array([[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]])
可以通过
实现c = a.reshape(a.shape[0], 1) # or c = a; c.shape = (c.shape[0], 1)
c.shape # (10, 1)
令我惊讶的是,它的形状为(10, 1)
而不是(1, 10)
。
在Octave / Scilab中,我可以这样做:
N = 10
b = 0:(N-1)
a = b'
size(b) % ans = 1 10
size(a) % ans = 10 1
我了解numpy ndarray并不是矩阵(如here所述),但是numpy的转置函数的行为对我而言毫无意义!如果您能帮助我了解这种行为的合理性以及我在这里缺少的内容,我将不胜感激。
PS 因此,到目前为止,我了解的是b = a.transpose()
相当于b = a; b.shape = b.shape[::-1]
,如果您拥有(N, 1)
的“二维数组”,返回一个(1, N)
形状的数组,就像您期望的转置运算符一样。但是,numpy似乎将(N,)
的“ 1D数组”视为0D标量。我认为他们应该将这个方法命名为其他方法,因为这很容易引起误解/混淆。
答案 0 :(得分:3)
要更好地理解numpy数组,您应该看一下这篇评论文章:The NumPy array: a structure for efficient numerical computation
简而言之,numpy ndarray具有称为跨步的属性,即
在内存中跳过以继续进行下一个元素的字节数。 例如,对于字节数组(10,10),步幅可以是(10, 1),换句话说:继续执行一个字节到达下一列,然后再十 个字节来定位下一行。
对于您的ndarray a
,a.stride
= (8,)
,这表明它仅是一维的,要到达该单维的下一个元素,您需要前进内存中有8个字节(每个int为64位)。
步幅对于表示转置很有用:
通过修改步幅,例如,可以转置数组或 以零成本进行了整形(无需复制任何内存)。
因此,如果存在二维ndarray,例如说b = np.ones((3,5))
,则b.strides
= (40, 8)
,而b.transpose().strides
= (8, 40)
。因此,如您所见,转置的2D-ndarray就是完全相同的数组,其步幅已重新排序。而且由于您的一维ndarray只有一维,因此交换其步幅的值(即进行其转置)不会做任何事情。
答案 1 :(得分:1)
您已经提到numpy数组不是矩阵。转置功能的定义如下
排列数组的尺寸。
这意味着numpy的转置方法会将数据从一个维度移动到另一个维度。由于一维数组只有一个维度,因此没有其他维度可以移动数据t0。因此,您需要在转置生效之前添加尺寸。与高维数组(3D,4D ...)数组保持一致时,这种行为也是有意义的。
有一种干净的方法来实现您想要的东西
N = 10
a = np.arange(N)
a[ :, np.newaxis]