Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way to broadcast arrays?

I want to broadcast an array b to the shape it would take if it were in an arithmetic operation with another array a.

For example, if a.shape = (3,3) and b was a scalar, I want to get an array whose shape is (3,3) and is filled with the scalar.

One way to do this is like this:

>>> 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]])

Although this works practically, I can't help but feel it looks a bit weird, and wouldn't be obvious to someone else looking at the code what I was trying to do.

Is there any more elegant way to do this? I've looked at the documentation for np.broadcast, but it's orders of magnitude slower.

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
like image 855
user545424 Avatar asked Jul 24 '12 00:07

user545424


People also ask

Is it possible to broadcast an array of arrays?

That being said, it does not work for all cases, and in fact imposes a strict rule that must be satisfied for broadcasting to be performed. Arithmetic, including broadcasting, can only be performed when the shape of each dimension in the arrays are equal or one has the dimension size of 1.

What is array broadcasting in NumPy?

Array Broadcasting Broadcasting is the name given to the method that NumPy uses to allow array arithmetic between arrays with a different shape or size. Although the technique was developed for NumPy, it has also been adopted more broadly in other numerical computational libraries, such as Theano, TensorFlow, and Octave.

How to broadcast on arrays in Julia?

The arguments we can pass in the broadcast () function are as follows: We can use the dot operator (.+, .-, .*, .=) to implement the same operations we did with the broadcast () function Julia provides us with many functions that can broadcast on arrays, applying various operations.

What is the use of broadcasting in Python?

Although the technique was developed for NumPy, it has also been adopted more broadly in other numerical computational libraries, such as Theano, TensorFlow, and Octave. Broadcasting solves the problem of arithmetic between arrays of differing shapes by in effect replicating the smaller array along the last mismatched dimension.


2 Answers

If you just want to fill an array with a scalar, fill is probably the best choice. But it sounds like you want something more generalized. Rather than using broadcast you can use broadcast_arrays to get the result that (I think) you want.

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

This generalizes to any two broadcastable shapes:

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

It's not quite as fast as your ufunc-based method, but it's still on the same order of magnitude:

>>> %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

But scalars, fill is still the clear front-runner:

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

Finally, further testing shows that the fastest approach -- in at least some cases -- is to multiply by 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
like image 190
senderle Avatar answered Sep 19 '22 11:09

senderle


The fastest and cleanest solution I know is:

b_arr = numpy.empty(a.shape)  # Empty array
b_arr.fill(b)  # Filling with one value
like image 20
Eric O Lebigot Avatar answered Sep 22 '22 11:09

Eric O Lebigot