为什么numpy切片会产生一维数组?

Why numpy slicing will produce one-dimension array?

我正在通过 YouTube 教程学习 numpy。在一段视频中,他证明了

wine_data_arr[:, 0].shape

其中 wine_data_arr 是从 sklearn 导入的二维 numpy 数组。结果是(178,),他说“是一维数组”。但是在数学中,例如这个

[1,2,3]

可以表示一个 1×3 的矩阵,其维度为 2。所以我的问题是为什么 wine_data_arr[:, 0] 是一维数组?我想这个定义在某些情况下一定有用。那么情况是怎样的呢?

尝试更具体:在编写 wine_data_arr[:, 0] 时,我提供了 两个 参数,即 :0,结果是 一个维度。当我写wine_data_arr[:, (0,4)]时,我仍然提供两个参数:(0,4),一个元组,结果是两个维度。为什么不都产生二维矩阵?

简短的回答:这是约定。

在深入细节之前,让我澄清一下,例如,NumPy 中的“维数”与数学中的“维数”不同。在数学中,[1, 2, 3] 是一个 three-dimensional 向量,如果需要,也可以是一维矩阵。然而,这里的维数实际上是指数组的“物理”维度,即数组(或矩阵,或张量等)中存在多少个轴。

现在让我回到您的问题,即为什么“这个”特定的数组维度定义有帮助。我接下来要说的有点哲学意义,是我自己的看法。从本质上讲,这一切都归结为程序员之间的交流。例如,当你正在阅读一些 Python 代码的文档并且想知道输出数组的维数时,确定文档可以写“N x M x ...”然后仔细定义什么 N,M 等。 是。但在许多情况下,仅轴数(或 NumPy 中提到的“维数”)可能足以告知您。在这种情况下,文档变得更加清晰易读,同时提供了有关预期结果的足够信息。

即使它们“看起来”相同,向量也与矩阵不同。考虑:

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

当像

那样对 two-dimensional 数组进行切片时
>>> wine_data_arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> wine_data_arr
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

您可以使用整数索引请求 lower-dimensional 组件(单个行或列)

>>> wine_data_arr[:,0]
array([1, 4, 7])
>>> wine_data_arr[0,:]
array([1, 2, 3])

或 same-dimensional 使用切片索引的“片段”:

>>> wine_data_arr[:, 0:1]
array([[1],       
       [4],
       [7]])

如果您使用 两个 整数索引,您将得到数组的单个 zero-dimensional 元素:

>>> wine_data_arr[0,0]
1

numpy 中,数组可以有 0、1、2 或更多维度。与 MATLAB 相比,没有 2d 下边界。此外 numpy 在显示和索引方面与 Python 列表基本一致。 MATLAB 通常遵循线性代数约定,但我确信数组和向量还有其他数学定义。在物理学中 vector 表示 space 中的一个点或一个方向,而不是 2d 'column vector' 或 'row vector'.

列表:

In [159]: alist = [1, 2, 3]
In [160]: len(alist)
Out[160]: 3

由这个列表组成的数组:

In [161]: arr = np.array(alist)
In [162]: arr.shape
Out[162]: (3,)

索引列表会移除一层嵌套。对数组进行标量索引会删除一个维度。参见

https://numpy.org/doc/stable/user/basics.indexing.html

In [163]: alist[0]
Out[163]: 1
In [164]: arr[0]
Out[164]: 1

一个二维数组:

In [166]: marr = np.arange(4).reshape(2, 2)
In [167]: marr
Out[167]: 
array([[0, 1],
       [2, 3]])

同样,标量索引删除了一个维度:

In [169]: marr[0,:]
Out[169]: array([0, 1])
In [170]: marr[:, 0]
Out[170]: array([0, 2])
In [172]: marr[1, 1]
Out[172]: 3

使用列表或切片建立索引保留维度:

In [173]: marr[0, [1]]
Out[173]: array([1])
In [174]: marr[0, 0:1]
Out[174]: array([0])

计数 [] 以确定维度。