Hello all I'm trying to write a function that takes a scalar, 0d-, 1d- or 2d array and returns a scalar or an array obtained by performing some computations on this input argument. When the output of such a function is the same size as input, one can do the following to preallocate the output array: def f(a): arra = asarray(a) if a.ndim > 2: raise ValueError('invalid dimensions') b = empty_like(arra) # do some operations on arra and put the values in b return b However, when the output array only depends on the size of a, but isn't exactly the same, things seem to get more complicated. Consider a function that operates on the rows of a (or the "row" if a is 1d or 0d or a scalar). For every row of length n, the function might return a row of length (n/2 + 1) if n is even or a row of length (n + 1)/2 if n is odd. Thus, depending on the shape of a, empty must be called with one of three different shapes. def outsize(n): if n % 2 == 0: return n/2+1 return (n+1)/2 if arra.ndim == 0: b = empty(()) elif arra.ndim == 1: b = empty((outsize(arra.shape[0]),)) else: b = empty((arra.shape[0],outsize(arra.shape[1])) To me this seems like a lot of code that can could be simpler if there was a function to get the size of an array that returns a useful value even if a particular dimension doesn't exist, much like MATLAB's size, where one can write: b = zeros(size(a,1),outsize(size(a,2))); function [m]=outsize(n) if mod(n, 2) == 0; m = n/2+1; else m =(n+1)/2; end and still have it work with scalars, 1d arrays and 2d arrays. Even if there were such a function for NumPy, this still leaves the problem that the output is going to have the wrong shape for 0d and 1d arrays, specifically (1,1) and (outsize(n),1) instead of () and (outsize(n),). This problem is solved in MATLAB where there is no distinction between 1 and [1]. How do you guys deal with this problem in your functions? Regars Albert
On 2/24/06, Albert Strasheim <fullung@gmail.com> wrote:
def outsize(n): if n % 2 == 0: return n/2+1 return (n+1)/2 if arra.ndim == 0: b = empty(()) elif arra.ndim == 1: b = empty((outsize(arra.shape[0]),)) else: b = empty((arra.shape[0],outsize(arra.shape[1]))
Try
empty(map(outsize, arra.shape))
This problem is solved in MATLAB where there is no distinction between 1 and [1].
How do you guys deal with this problem in your functions?
You might want to take a look at the parallel thread under "A case for rank-0 arrays."
On 2/24/06, Sasha <ndarray@mac.com> wrote:
Try
empty(map(outsize, arra.shape)) Oops. I did not realize that you want to apply outsize to the last dimension only. For ndim>1, you can do
empty(arra.shape[:-1]+(outsize(arra.shape[-1]),))
That will not work work for scalars though, but you might want to rethink whether your function makes sense for scalars. Remember, 1 is not the same as [1] in python, you maybe trying to copy MATLAP design too literally.
Hello On Fri, 24 Feb 2006, Sasha wrote:
On 2/24/06, Sasha <ndarray@mac.com> wrote:
Try
empty(map(outsize, arra.shape)) Oops. I did not realize that you want to apply outsize to the last dimension only. For ndim>1, you can do
empty(arra.shape[:-1]+(outsize(arra.shape[-1]),))
Thanks, this works nicely. My code: outsize = lambda n: (n/2+1, (n+1)/2)[(n%2)%2] b = empty(a.shape[:-1]+(outsize(a.shape[-1]),)) (One line less than MATLAB ;-))
That will not work work for scalars though, but you might want to rethink whether your function makes sense for scalars. Remember, 1 is not the same as [1] in python, you maybe trying to copy MATLAP design too literally.
Personally, I think asarray(scalar) should return something that can actually be used as an array (i.e. has a proper shape and ndim), but if all NumPy functions operate only on arrays to begin with, I could live with that too. Regards Albert
Albert Strasheim wrote:
Personally, I think asarray(scalar) should return something that can actually be used as an array (i.e. has a proper shape and ndim),
What is the proper shape and numdim? Only your app knows. What I generally do with a function i want to take an array or "something that can be turned into an array" is to use asarray, then set the shape to what I am expecting:
import numarray as N
def rank1(input): ... A = N.asarray(input) ... A.shape = (-1) ... print repr(A) ... rank1((5,6,7,8)) array([5, 6, 7, 8]) rank1(5) array([5])
def rank2(input): ... A = N.asarray(input) ... A.shape = (-1, 2) ... print repr(A) ... rank2((2,3)) array([[2, 3]]) rank2(((2,3), (4,5), (6,7))) array([[2, 3], [4, 5], [6, 7]])
-Chris -- Christopher Barker, Ph.D. Oceanographer NOAA/OR&R/HAZMAT (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov
participants (3)
-
Albert Strasheim -
Christopher Barker -
Sasha