6

我想将一个数组广播b到它与另一个数组进行算术运算时所采用的形状a

例如,如果a.shape = (3,3)andb是一个标量,我想得到一个数组,其形状是(3,3)并且用标量填充。

一种方法是这样的:

>>> import numpy as np
>>> a = np.arange(9).reshape((3,3))
>>> b = 1 + a*0
>>> b
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

虽然这实际上可行,但我不禁觉得它看起来有点奇怪,并且对于其他查看我正在尝试做的代码的人来说并不明显。

有没有更优雅的方法来做到这一点?我查看了 的文档np.broadcast,但速度要慢几个数量级。

In [1]: a = np.arange(10000).reshape((100,100))

In [2]: %timeit 1 + a*0
10000 loops, best of 3: 31.9 us per loop

In [3]: %timeit bc = np.broadcast(a,1);np.fromiter((v for u, v in bc),float).reshape(bc.shape)
100 loops, best of 3: 5.2 ms per loop

In [4]: 5.2e-3/32e-6
Out[4]: 162.5
4

4 回答 4

7

如果您只想用标量填充数组,fill可能是最好的选择。但听起来你想要更通用的东西。而不是使用broadcast你可以使用broadcast_arrays来获得(我认为)你想要的结果。

>>> a = numpy.arange(9).reshape(3, 3)
>>> numpy.broadcast_arrays(a, 1)[1]
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

这推广到任何两个可广播的形状:

>>> numpy.broadcast_arrays(a, [1, 2, 3])[1]
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

它不如ufunc基于 - 的方法快,但仍处于同一数量级:

>>> %timeit 1 + a * 0
10000 loops, best of 3: 23.2 us per loop
>>> %timeit numpy.broadcast_arrays(a, 1)[1]
10000 loops, best of 3: 52.3 us per loop

但标量fill仍然是明显的领跑者:

>>> %timeit b = numpy.empty_like(a, dtype='i8'); b.fill(1)
100000 loops, best of 3: 6.59 us per loop

最后,进一步的测试表明,最快的方法——至少在某些情况下——是乘以ones

>>> %timeit numpy.broadcast_arrays(a, numpy.arange(100))[1]
10000 loops, best of 3: 53.4 us per loop
>>> %timeit (1 + a * 0) * numpy.arange(100)
10000 loops, best of 3: 45.9 us per loop
>>> %timeit b = numpy.ones_like(a, dtype='i8'); b * numpy.arange(100)
10000 loops, best of 3: 28.9 us per loop
于 2012-07-24T02:48:31.113 回答
2

fill听起来像最简单的方法:

>>> a = np.arange(9).reshape((3,3))
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> a.fill(10)
>>> a
array([[10, 10, 10],
       [10, 10, 10],
       [10, 10, 10]])

编辑:arange正如@EOL 指出的那样,如果要创建一个新数组(或任何形状),则不需要这样做np.empty((100,100))更好。

时间:

In [3]: a = np.arange(10000).reshape((100,100))
In [4]: %timeit 1 + a*0
100000 loops, best of 3: 19.9 us per loop

In [5]: a = np.arange(10000).reshape((100,100))
In [6]: %timeit a.fill(1)
100000 loops, best of 3: 3.73 us per loop
于 2012-07-24T02:45:34.403 回答
2

我知道的最快和最干净的解决方案是:

b_arr = numpy.empty(a.shape)  # Empty array
b_arr.fill(b)  # Filling with one value
于 2012-07-24T02:49:21.663 回答
1

如果您只需要将标量广播到某个任意形状,则可以执行以下操作:

a = b*np.ones(shape=(3,3))

编辑:np.tile更笼统。您可以使用它来复制任意数量的维度中的任何标量/向量:

b = 1
N = 100
a = np.tile(b, reps=(N, N))
于 2012-07-24T02:07:54.627 回答