首页 > 解决方案 > 是否存在作用于现有数组的“np.repeat”?

问题描述

我有一个大型 NumPy 数组,我想在循环的每次迭代中填充新数据。数组中填充了沿轴 0 重复的数据,例如:

[[1, 5],
 [1, 5],
 [1, 5],
 [1, 5]]

我知道如何在每次迭代中从头开始创建这个数组:

x = np.repeat([[1, 5]], 4, axis=0)

但是,我不想每次都创建一个新数组,因为它是一个非常大的数组(比 4x2 大得多)。相反,我想使用上面的代码提前创建数组,然后在每次迭代时用新数据填充数组。

np.repeat()返回一个新数组,而不是作用于现有数组。是否有np.repeat()用于填充现有数组的等价物?

标签: pythonnumpy

解决方案


正如我们在评论中指出的那样,您可以使用广播分配来用适当大小的 1d 数组填充您的 2d 数组:

x[...] = [1, 5]

如果您的大数组在每一行中总是包含相同的项目(即您以后不会更改这些预设值),那么您几乎可以肯定在代码的后面部分使用广播,并且只使用初始值x,例如

x = np.array([[1, 5]])

该数组的形状与您在上面示例中可能具有的(1, 2)其他形状数组广播兼容。(4, 2)

如果您总是需要在每一行中使用相同的值,并且由于某种原因您不能使用广播(这两种情况都不太可能),您可以使用broadcast_to创建具有显式 2d 形状的数组而无需复制内存:

x_bc = np.broadcast_to([1, 5], (4, 2)) # broadcast 1d [1, 5] to shape (4, 2)

这可能会起作用,因为它具有正确的形状,内存中只有 2 个独特的元素:

>>> x_bc
array([[1, 5],
       [1, 5],
       [1, 5],
       [1, 5]])

>>> x_bc.strides
(0, 8)

但是你不能改变它,因为它是一个只读视图:

>>> x_bc[0, :] = [2, 4]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-35-ae12ecfe3c5e> in <module>
----> 1 x_bc[0, :] = [2, 4]

ValueError: assignment destination is read-only

因此,如果您只需要在每一行中使用相同的值并且您不能使用广播并且您想稍后改变这些相同的行,您可以使用跨步技巧将相同的一维数据映射到一个二维数组:

>>> x_in = np.array([1, 5])
... x_strided = np.lib.stride_tricks.as_strided(x_in, shape=(4,) + x_in.shape,
...                                             strides=(0,) + x_in.strides[-1:])

>>> x_strided
array([[1, 5],
       [1, 5],
       [1, 5],
       [1, 5]])

>>> x_strided[0, :] = [2, 4]

>>> x_strided
array([[2, 4],
       [2, 4],
       [2, 4],
       [2, 4]])

这为您提供了一个固定形状的二维数组,该数组始终包含一个唯一的行,并且对任何行进行变异会使其余行发生变异(因为基础数据仅对应于单行)。小心处理,因为如果你想要有两个不同的行,你将不得不做其他事情。


推荐阅读