用 x 零和其余零实例化一个矩阵

Posted

技术标签:

【中文标题】用 x 零和其余零实例化一个矩阵【英文标题】:Instantiate a matrix with x zeros and the rest ones 【发布时间】:2014-11-25 15:34:48 【问题描述】:

我希望能够快速实例化一个矩阵,其中一行中的前几个(可变数量)单元格为 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 作为默认值并替换零的方法。

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

【问题讨论】:

【参考方案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 零和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 的一维数组)进行比较时,广播开始了:

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) 非常感谢!解释可能对将来访问的人有用(尽管您现在可能只是在努力)。 其实我没有用方阵;( 不需要方阵。结果的形状是(len(arr), n),如答案中所述。刚好选了n=5作为例子。 @WarrenWeckesser 是的,我的错,我使用了错误的数组。【参考方案2】:

不像我想要的那样简洁(我正在尝试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],逐行创建数组。

【讨论】:

更新了问题以明确排除此答案为有效(我的错误),但可能对其他人仍然有用。 (不反对) @PascalvKooten 是的,刚刚注意到。很抱歉造成混乱。但是有一个更短的方法,请给我一分钟 :) 另外,请确保它也适用于非方阵。 @PascalvKooten 完成 - 请试试这个。 @PascalvKooten 我怀疑您是否会注意到这种小矩阵的任何显着差异。我更喜欢先写简单易读的代码,只有在发现并证明特定地方的性能问题后,再进行优化。

以上是关于用 x 零和其余零实例化一个矩阵的主要内容,如果未能解决你的问题,请参考以下文章

创建一个无法在其板条箱之外实例化的零大小结构的惯用方法是啥?

查找投影矩阵以创建零和向量

使用 OpenGL 3.3 进行实例化似乎很慢

跟我学算法-PCA(降维)基本原理推导

从零开始的Java开发1-3-1 Java面向对象:创建类实例化对象单一职责原则newthis构造方法

.(Java中)实例化对象:就是创建一个对象,用啥运算符来实现对象的实例化?