Is there a better way to broadcast arrays?

I want to pass array b to the form that it will 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 with the form (3,3) and filled with a scalar.

One way to do 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 in practice, I cannot help but feel that it looks a little strange, and it would not be obvious for anyone else to look at the code that I was trying to do.

Is there a more elegant way to do this? I looked at the documentation for np.broadcast , but several 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 
+6
source share
4 answers

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

 >>> 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 any two broadcast forms:

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

This is not as fast as your ufunc based ufunc , but it is still on the same level:

 >>> %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 are still clear front:

 >>> %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 - at least in some cases - is multiplied 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 
+7
source

fill sounds like the easiest way:

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

EDIT:. As @EOL points out, you don't need arange if you want to create a new array, np.empty((100,100)) (or any form) is better for this.

Timings:

 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 
+2
source

If you just need to pass the scalar to arbitrary form, you can do something like this:

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

Edit: np.tile is more general. You can use it to duplicate any scalar / vector in any number of dimensions:

 b = 1 N = 100 a = np.tile(b, reps=(N, N)) 
+1
source

The fastest and cleanest solution I know:

 b_arr = numpy.empty(a.shape) # Empty array b_arr.fill(b) # Filling with one value 
+1
source

Source: https://habr.com/ru/post/921166/


All Articles