我希望能够快速实例化一个矩阵,其中一行中的前几个(可变数量)单元格为 0,其余单元格为 0。

想象一下,我们想要一个 3x4 的矩阵。

我首先将矩阵实例化为所有矩阵:

ones = np.ones([4,3])

然后想象我们有一个数组,它宣布有多少个前导零:
arr = np.array([2,1,3,0]) # first row has 2 zeroes, second row 1 zero, etc

要求的结果:
array([[0, 0, 1],
       [0, 1, 1],
       [0, 0, 0],
       [1, 1, 1]])

显然,这也可以以相反的方式完成,但我会考虑 1 是默认值的方法,零将被替换。

避免一些愚蠢循环的最佳方法是什么?

最佳答案

这是一种方法。 n 是结果中的列数。行数由 len(arr) 决定。

In [29]: n = 5

In [30]: arr = np.array([1, 2, 3, 0, 3])

In [31]: (np.arange(n) >= arr[:, np.newaxis]).astype(int)
Out[31]:
array([[0, 1, 1, 1, 1],
       [0, 0, 1, 1, 1],
       [0, 0, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [0, 0, 0, 1, 1]])

有两个部分来解释这是如何工作的。首先,如何用 m 0 和 n-m 来创建一行?为此,我们使用 np.arange 创建一个值为 [0, 1, ..., n-1]` 的行:
In [35]: n
Out[35]: 5

In [36]: np.arange(n)
Out[36]: array([0, 1, 2, 3, 4])

接下来,将该数组与 m 进行比较:
In [37]: m = 2

In [38]: np.arange(n) >= m
Out[38]: array([False, False,  True,  True,  True], dtype=bool)

这给出了一个 bool 值数组;第一个 m 值为 False,其余为 True。通过将这些值转换为整数,我们得到一个由 0 和 1 组成的数组:
In [39]: (np.arange(n) >= m).astype(int)
Out[39]: array([0, 0, 1, 1, 1])

要对一组 m 值(您的 arr )执行此操作,我们使用 broadcasting ;这是解释的第二个关键思想。

请注意 arr[:, np.newaxis] 给出的内容:
In [40]: arr
Out[40]: array([1, 2, 3, 0, 3])

In [41]: arr[:, np.newaxis]
Out[41]:
array([[1],
       [2],
       [3],
       [0],
       [3]])

也就是说,arr[:, np.newaxis]arr 重塑为形状为 (5, 1) 的二维数组。 (可以使用 arr.reshape(-1, 1) 代替。)现在,当我们将其与 np.arange(n) (长度为 n 的一维数组)进行比较时,广播开始了:
In [42]: np.arange(n) >= arr[:, np.newaxis]
Out[42]:
array([[False,  True,  True,  True,  True],
       [False, False,  True,  True,  True],
       [False, False, False,  True,  True],
       [ True,  True,  True,  True,  True],
       [False, False, False,  True,  True]], dtype=bool)

正如@RogerFan 在他的评论中指出的那样,这基本上是使用 >= 操作的参数的外积。

输入 int 的最后一次转换给出了所需的结果:
In [43]: (np.arange(n) >= arr[:, np.newaxis]).astype(int)
Out[43]:
array([[0, 1, 1, 1, 1],
       [0, 0, 1, 1, 1],
       [0, 0, 0, 1, 1],
       [1, 1, 1, 1, 1],
       [0, 0, 0, 1, 1]])

10-07 19:17
查看更多