numpy:为什么(x,1)和(x,)的维度有区别?

24

我想知道在numpy中为什么会存在维度为(length, 1)的一维数组和维度为(length,)的一维数组两种情况。

我经常遇到这种情况,例如在使用np.concatenate()时,需要先进行reshape步骤,或者我可以直接使用hstack/vstack。

我无法想象为什么这种行为是有必要的。有人能解释一下吗?

编辑:
其中一个评论建议我的问题可能是重复的。我更关注Numpy的基本工作逻辑,而不是区分一维和二维数组之间的区别,这是我认为被提到的线程的重点。


2
(x,) 指的是向量,而不是矩阵。 - kennytm
2
NumPy是围绕n维数组而构建的,而不是矩阵。 - user2357112
@kennytm 感谢您的回复,但是为什么向量不能表示为 (x,1) 呢? - Dahlai
@user2357112已经相应地重新表述了。 - Dahlai
3
一个形状为(x,1)的numpy数组是二维数组。第二个维度恰好长度为1。形状为(x,)的numpy数组是一维数组。它没有第二个维度。对于numpy的大部分内容,您可以停止考虑“向量”和“矩阵”,只需考虑n维数组即可。 - Warren Weckesser
可能是重复的问题:numpy:形状各异的1D数组 - Benjamin
2个回答

13
ndarray 的数据存储为一维缓冲区 - 只是一块内存。数组的多维特性由shapestrides属性及使用它们的代码产生。 numpy的开发者选择允许任意数量的维度,因此形状和步幅表示为任意长度的元组,包括0和1。
相比之下,MATLAB是围绕着为矩阵运算开发的FORTRAN程序构建的。在早期,MATLAB中的所有东西都是二维矩阵,到了2000年左右(v3.5),它被推广为允许超过2d,但从未少于2d。 numpynp.matrix仍然遵循旧的2d MATLAB约束。
如果你来自MATLAB世界,你习惯于这些2个维度和行向量与列向量之间的区别。但在数学和物理学中,并没有受到MATLAB影响,向量是一个一维数组。Python列表本质上是1d的,而且 c 数组也是1d的。要得到2d,必须有列表的列表或指向数组的指针数组,带有x [1] [2]样式的索引。
查看这个数组及其变体的形状和步幅:
In [48]: x=np.arange(10)

In [49]: x.shape
Out[49]: (10,)

In [50]: x.strides
Out[50]: (4,)

In [51]: x1=x.reshape(10,1)

In [52]: x1.shape
Out[52]: (10, 1)

In [53]: x1.strides
Out[53]: (4, 4)

In [54]: x2=np.concatenate((x1,x1),axis=1)

In [55]: x2.shape
Out[55]: (10, 2)

In [56]: x2.strides
Out[56]: (8, 4)

MATLAB 在末尾添加新的维度。它像 order='F' 数组一样排序其值,可以很容易地将 (n,1) 矩阵转换为 (n,1,1,1)。默认情况下,numpy 的排序方式为 order='C',并且可以轻松地在开头扩展数组维度。利用广播时理解这一点至关重要。

因此,x1 + x 是一个 (10,1)+(10,) => (10,1)+(1,10) => (10,10)。

由于广播,(n,) 数组更像是一个行向量而不是列向量,与 (n,1) 不同。

In [64]: np.matrix(x)
Out[64]: matrix([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

In [65]: _.shape
Out[65]: (1, 10)
concatenate要求匹配维度,不使用广播调整维度。有一堆stack函数可以缓解这个限制,但它们会在使用concatenate之前调整维度。查看它们的代码(可读性很好的Python)。
因此,熟练使用numpy的用户需要熟悉通用的shape元组,包括空的()(0d数组),(n,) 1d和更高维度的数组。对于更高级的东西,了解步幅也很有帮助(例如查看转置的步幅和形状)。

谢谢,这对于理解Numpy行为的起源非常有帮助。我现在想知道这些一维数组的好处是什么。为什么它们不被隐藏在后台,让用户看到的一切都是至少一个(x,1)数组?是否存在特定情况下(x,)数组具有优势? - Dahlai
一个 (x,1) 会显示为一列。一个 (1,x) 会显示为一行,但是多了一组 []。我经常生成一维数组,例如 np.arange(10)。我可能会将其重塑为 (5,2)。只有在需要广播时才会添加尾随的 ,[:,None] - hpaulj
我们可以说 (x,) 是一个向量,而 (x,1) 则是一个矩阵吗? - weima

3
大部分涉及语法问题。这个元组(x)根本不是元组(只是多余的)。然而,(x,)是一个元组。
(x,)和(x,1)之间的区别甚至更深入。您可以查看先前问题的示例,例如此处。引用其中的示例,这是一个1D numpy数组:
>>> np.array([1, 2, 3]).shape
(3,)

但这个是二维的:
>>> np.array([[1, 2, 3]]).shape
(1, 3)

重新塑形不会复制除非需要,所以使用起来是安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接