我希望能够快速实例化一个矩阵,其中一行中的前几个(可变数量)单元格为0,其余为1。
想象一下,我们想要一个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是默认值的方法,并且将替换零。
避免一些愚蠢循环的最佳方法是什么?
答案 0 :(得分:6)
这是一种方式。 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
零和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)
它给出了一个布尔值数组;第一个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
的1-d数组)进行比较时,广播开始了:
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]])
答案 1 :(得分:1)
不像我想要的那样简洁(我正在尝试使用mask_indices
),但这也可以完成工作:
>>> n = 3
>>> zeros = [2, 1, 3, 0]
>>> numpy.array([[0] * zeros[i] + [1]*(n - zeros[i]) for i in range(len(zeros))])
array([[0, 0, 1],
[0, 1, 1],
[0, 0, 0],
[1, 1, 1]])
>>>
工作非常简单:连接所需的次数,单元素列表[0]
和[1]
,逐行创建数组。