是否有更好的广播阵列方式?

use*_*424 6 python numpy numpy-broadcasting

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

例如,如果a.shape = (3,3)并且b是标量,我想得到一个形状为(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]])
Run Code Online (Sandbox Code Playgroud)

虽然这实际上很有效,但我不禁觉得它看起来有点奇怪,并且对于那些看着代码的人来说,我试图做的事情并不明显.

有没有更优雅的方式来做到这一点?我查看了文档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
Run Code Online (Sandbox Code Playgroud)

sen*_*rle 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]])
Run Code Online (Sandbox Code Playgroud)

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

>>> numpy.broadcast_arrays(a, [1, 2, 3])[1]
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])
Run Code Online (Sandbox Code Playgroud)

它不如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
Run Code Online (Sandbox Code Playgroud)

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

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

最后,进一步的测试表明,最快的方法 - 至少在某些情况下 - 是乘以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
Run Code Online (Sandbox Code Playgroud)