2016-07-15 54 views
7

我想知道为什么在numpy中有维度(长度,1)的一维数组,还有一维维度数组(长度, )没有第二个值。numpy:为什么在(x,1)和(x,)维度之间存在差异

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

我想不出为什么这种行为是可取的理由。有人可以解释吗?

编辑:
有人建议通过评论我的问题是一个可能的重复。我对Numpy的底层工作更感兴趣,而不是认为1d和2d数组有区别,我认为这是所提到的线程的要点。

+1

'(x,)'是指向量,而不是矩阵。 – kennytm

+2

NumPy是围绕n维数组构建的,而不是矩阵。 – user2357112

+0

@kennytm感谢您的输入,但是向量不会被表示为'(x,1)'的原因是什么? – Dahlai

回答

9

ndarray的数据存储为1d缓冲区 - 只是一块内存。数组的多维性质由shapestrides属性以及使用它们的代码生成。

numpy开发人员选择,以允许尺寸的任意数量的,所以形状和进展被表示为任何长度的元组,包括0和1。

相反MATLAB是围绕而开发的FORTRAN程序建用于矩阵运算。在早期,MATLAB中的所有东西都是2d矩阵。大约在2000年(v3.5),它被推广到允许超过2d,但从不少于。 numpynp.matrix仍然遵循旧的2d MATLAB约束。

如果你来自MATLAB世界,你习惯了这两个维度,以及行向量和列向量之间的区别。但是在不受MATLAB影响的数学和物理学中,矢量是一维数组。 Python列表本质上是1d,与c数组一样。为了得到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,)阵列更像(1,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点是它需要匹配的尺寸。它不使用广播来调整尺寸。有许多功能可以缓解这种限制,但是他们在使用concatenate之前通过调整尺寸来实现。看看他们的代码(可读的Python)。

因此,一个熟练numpy的用户需要的舒适与广义shape元组,包括空()(0D阵列)(n,) 1D和向上。对于更高级的东西,理解大步也很有帮助(例如,看一下转置的步幅和形状)。

+0

谢谢这对理解Numpy的起源非常有用行为。我想知道现在这些1维数组的好处是什么。他们为什么不隐藏在引擎盖下,对用户来说,一切都是最小的'(x,1)'数组?是否有'(x,)'数组有优势的特定情况? – Dahlai

+0

'(x,1)'显示为一列。一个'(1,x)'作为一行,但有一组额外的[]。我一直生成1d阵列,例如'np.arange(10)'。我可能会把它重塑成'(5,2)'。只有当我需要广播它时,我才会添加末尾的','[:,None]'。 – hpaulj

+0

我们可以说'(x,)'是一个Vector,其中'(x,1)'是一个矩阵? – weima

2

其中大部分是语法问题。这个元组(x)根本不是元组(只是冗余)。然而,(x,)是。

(x,)和(x,1)之间的区别更进一步。你可以看看以前的问题的例子,如this。从它引用的例子,这是一个一维数组numpy的:

>>> np.array([1, 2, 3]).shape 
(3,) 

但是这一次是2D:

>>> np.array([[1, 2, 3]]).shape 
(1, 3) 

Reshape does not make a copy unless it needs to所以它应该是安全的使用。

相关问题