learning-notes icon indicating copy to clipboard operation
learning-notes copied to clipboard

在 NumPy 中,该怎么样索引一个矩阵的第 i 列,使其返回一个列向量?

Open daa233 opened this issue 7 years ago • 2 comments

例如有下面的 3 行 4 列的矩阵 a

>>> import numpy as np
>>> a = np.arange(12).reshape(3, 4)
>>> print(a)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

应该怎么样索引,才能得到 a 的第 i 列呢?例如,我想索引第 0 列,得到的结果应该是一个列向量 [[0] [4] [8]]

尝试的方法:

  1. 先切片,再 reshape。切片后返回的结果是一个一维数组,通过 reshape 变为列向量。需要注意切片的方式。
>>> a[:, 0]
array([0, 4, 8])
>>> col_0 = a[:, 0].reshape((a.shape[0], 1))
>>> print(col_0)
[[0]
 [4]
 [8]]
>>> >>> a[:][0]  # wrong slicing to get the column
array([0, 1, 2, 3])
  1. np.hsplit() 分割。成功,但是有些啰嗦,因为这不是 hsplit 的本职工作。
>>> col_0, dummy = np.hsplit(a, np.array([1]))  # index the 0th column of a
>>> print(col_0)
[[0]
 [4]
 [8]]
>>> col_1 = np.hsplit(a, np.array([1, 2]))[1]  # index the 1st column of a
>>> print(col_1)
[[1]
 [5]
 [9]]
  1. for 循环索引。嗯,先忽略它。

daa233 avatar Oct 07 '17 02:10 daa233

  1. 利用布尔值 True 索引,并将返回结果由行向量转置为列向量。哈哈,这种方式比较花哨,不知道怎么就尝试出来了。😅 虽然看上去很酷,但我还不知道该怎么解释。
>>> col_0 = a[:, 0][True].T
>>> print(col_0)
[[0]
 [4]
 [8]]
>>> col_1 = a[:, 1][True].T
>>> print(col_1)
[[1]
 [5]
 [9]]

使用布尔值索引的”正常“打开方式应该是这样:

>>> b = np.arange(1, 6)
>>> print(b)
[1 2 3 4 5]
>>> bi = np.array([True, False, True, False, True])
>>> print(b[bi])
[1 3 5]

EDIT

这里 https://stackoverflow.com/questions/45493270/what-does-xfalse-do-in-numpy 给出了解释,但我没有看懂。而且这个功能可能之前的版本并不支持,所以不要这样使用它。

EDIT 2

a[True]a[np.newaxis] 是等价的。

>>> a = np.arange(5)
>>> print(a)
[0 1 2 3 4]
>>> a[np.newaxis]
array([[0, 1, 2, 3, 4]])
>>> a[np.newaxis]
array([[0, 1, 2, 3, 4]])
>>> a = np.arange(5)
>>> print(a)
[0 1 2 3 4]
>>> a[True]
array([[0, 1, 2, 3, 4]])
>>> a[True]
array([[0, 1, 2, 3, 4]])

np.newaxis 的用法如下:

>>> a = np.arange(5)
>>> print(a)
[0 1 2 3 4]
>>> a[np.newaxis, :]  # add a new axis in front
array([[0, 1, 2, 3, 4]])
>>> a[np.newaxis, :].shape
(1, 5)
>>> a[:, np.newaxis]  # add a new axis at behind
array([[0],
       [1],
       [2],
       [3],
       [4]])
>>> a[:, np.newaxis].shape
(5, 1)
>>>
>>> a = np.arange(6)
>>> a = a.reshape(2, 3)
>>> print(a)
[[0 1 2]
 [3 4 5]]
>>> a = a.reshape(2, 3)
>>> print(a)
[[0 1 2]
 [3 4 5]]
>>> a[np.newaxis, :]
array([[[0, 1, 2],
        [3, 4, 5]]])
>>> a[np.newaxis, :].shape
(1, 2, 3)
>>> a[:, np.newaxis]
array([[[0, 1, 2]],

       [[3, 4, 5]]])
>>> a[:, np.newaxis].shape
(2, 1, 3)
>>> a[:, :, np.newaxis]
array([[[0],
        [1],
        [2]],

       [[3],
        [4],
        [5]]])
>>> a[:, :, np.newaxis].shape
(2, 3, 1)
>>>
>>> a[:, :, True]
array([[[0],
        [1],
        [2]],

       [[3],
        [4],
        [5]]])
>>> a[:, :, True].shape
(2, 3, 1)
>>> a[:, :, False]
array([], shape=(2, 3, 0), dtype=int64)

SUMMARY

a[...True...] 等价于 a[...np.newaxis...],可以在指定的位置添加一个长度为 1 的维度。特殊地,a[True] 等价于 a[np.newaxis],会在最前面增加一个长度为 1 的维度。a[...False...]a[...True...] 类似,会在指定的位置增加一个长度为 0 的维度,不选中任何元素。

如果 a 是一个一维数组,可以分别利用 a[True]a[True].T 将其转换为行向量和列向量。

daa233 avatar Oct 07 '17 03:10 daa233

  1. 【最佳方式】 还是切片,不过稍有不同。https://stackoverflow.com/questions/4455076/how-to-access-the-ith-column-of-a-numpy-multidimensional-array
>>> col_0 = a[:, [0]]  # index the 0th column of a and return a column vector
>>> print(col_0)
[[0]
 [4]
 [8]]
>>> col_1_2 = a[:, [1, 2]]   # index the 1st and 2nd column of a
>>> print(col_1_2)
[[ 1  2]
 [ 5  6]
 [ 9 10]]
>>> col_1_3 = a[:, [1, 3]]  # index the 1st and 3rd column of a
>>> print(col_1_3)
[[ 1  3]
 [ 5  7]
 [ 9 11]]

daa233 avatar Oct 08 '17 01:10 daa233