1

I would like to apply a function to a monodimensional array 3 elements at a time, and output for each of them a single element.

for example I have an array of 13 elements:

a = np.arange(13)**2

and I want to apply a function, let's say np.std as an example.

Here is the equivalent list comprehension:

[np.std(a[i:i+3]) for i in range(0, len(a),3)] 
[1.6996731711975948,
 6.5489609014628334,
 11.440668201153674,
 16.336734339790461,
 0.0]

does anyone know a more efficient way using numpy functions?

Andrea Zonca
  • 8,378
  • 9
  • 42
  • 70

3 Answers3

5

The simplest way is to reshape it and apply the function along an axis.

import numpy as np
a = np.arange(12)**2
b = a.reshape(4,3)
print np.std(b, axis=1)

If you need a little better performance than that, you could try stride_tricks. Below is the same as above except using stride_tricks. I was wrong about the performance gain, because as you can see below, b becomes exactly the same view as b above. I wouldn't be surprised if they compiled to exactly the same thing.

import numpy as np
a = np.arange(12)**2
b = np.lib.stride_tricks.as_strided(a, shape=(4,3), strides=(a.itemsize*3, a.itemsize))
print np.std(b, axis=1)
Community
  • 1
  • 1
Paul
  • 42,322
  • 15
  • 106
  • 123
  • Stride tricks is what I was looking for, would you have an example for this case? It looks pretty complex to use – Andrea Zonca Mar 02 '11 at 07:02
  • @Andrea Z: See my update. What `as_strided` allows you to do is to change the shape and the strides at the same time, allowing a change in the apparent size of the array. Since you don't need to change the strides or the size in this case, it is exactly equivalent to using `reshape`. See this http://stackoverflow.com/questions/4923617/efficient-numpy-2d-array-construction-from-1d-array post for more explanation. – Paul Mar 02 '11 at 08:04
  • and if the function you want to use doesn't have an `axis=` parameter, use [numpy.apply_along_axis](http://docs.scipy.org/doc/numpy/reference/generated/numpy.apply_along_axis.html) – endolith Nov 29 '12 at 03:55
0

Are you talking about something like vectorize? http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

J. Taylor
  • 4,567
  • 3
  • 35
  • 55
0

You can reshape it. But that does require that the size not change. If you can tack on some bogus entries at the end you can do this:

[np.std(s) for s in a.reshape(-1,3)]
Keith
  • 42,110
  • 11
  • 57
  • 76
  • What you mean with `If you can tack on some bogus entries ...`? I don't think that's possible with `reshape`, but with `stride tricks` that's easily the case. – eat Mar 02 '11 at 08:41
  • You can't reshape with partial rows resulting. To make it rectangular some might have to be added. But striding is better in that case. – Keith Mar 02 '11 at 11:30