Re: [Numpy-discussion] Why is the shape of a singleton array the empty tuple?
First, to David's routine: 2010/3/7 David Goldsmith d.l.goldsm...@gmail.com: def convert_close(arg): arg = N.array(arg) if not arg.shape: arg = N.array((arg,)) if arg.size: t = N.array([0 if N.allclose(temp, 0) else temp for temp in arg]) if len(t.shape) - 1: return N.squeeze(t) else: return t else: return N.array() Ok, chaps, let's code: import numpy def convert_close(ndarray, atol = 1e-5, rtol = 1e-8): ndarray_abs = abs(ndarray) mask = (ndarray_abs atol + rtol * ndarray_abs) return ndarray * mask python -i close.py a = numpy.asarray([1e-6]) convert_close(a) array([ 0.]) a = numpy.asarray([1e-6, 1]) convert_close(a) array([ 0., 1.]) a = numpy.asarray(1e-6) convert_close(a) 0.0 a = numpy.asarray([-1e-6, 1]) convert_close(a) array([ 0., 1.]) It's not as good as Robert's (so far virtual) solution, but :-) On Sat, Mar 6, 2010 at 10:26 PM, Ian Mallett geometr...@gmail.com wrote: On Sat, Mar 6, 2010 at 9:46 PM, David Goldsmith d.l.goldsm...@gmail.com wrote: Thanks, Ian. I already figured out how to make it not so, but I still want to understand the design reasoning behind it being so in the first place (thus the use of the question why (is it so), not how (to make it different)). 1. First from a mathematical point of view (don't be frightened): When an array has shape ndarray.shape, then the number of elements contained is: numpy.asarray(ndarray.shape).mul() When I type now: numpy.asarray([]).prod() 1.0 This is the .shape of an scalar ndarray (without any strides), and therefore such a scalar ndarray holds exactly one item. Or, for hard-core friends (-: numpy.asarray([[]]) array([], shape=(1, 0), dtype=float64) numpy.asarray([[]]).prod() 1.0 So, ndarrays without elements yield .prod() == 1.0. This is sensible, because the product shall be algorithmically defined as: def prod(ndarray): product = 1.0 for item in ndarray.flatten(): product *= item return product Thus, the product of nothing is defined to be one to be consistent. One would end up with the same using a recursive definition of prod() instead of this iterative one. 2. From programmer's point of view. You can always write: ndarray[()]. This means, to give no index at all. Indeed, writing: ndarray[1, 2] is equivalent to writing: ndarray[(1, 2)] , as keys are always passed as a tuple or a scalar. Scalar in case of: ndarray[42] . Now, the call: ndarray[()] shall return 'something', which is the complete ndarray, because we didn't indice anything. For multidimensional arrays: a = numpy.ndarray([[1, 2], [3, 4]]) the call: a[0] shall return: array([1, 2]). This is clear. But now, what to return, if we consume all the indices available, e.g. when writing: a[0, 0] ? This means, we return the scalar array array(1) . That's another meaning of scalar arrays. When indicing an ndarray a with a tuple of length N_key, without slices, the return shape will be always: a.shape[N_key:] This means, using all indices available returns a shape: a.shape[a.ndim:] == [] , i.e., a scalar without shape. To conclude, everything is consistent when allowing scalar arrays, and everything breaks down if we don't. They are some kind of 0, like the 0 in the whole numbers, which the Roman's didn't know of. It makes things simpler (and more consistent). Also it unifies scalars and arrays to only on kind of type, which is a great deal. Friedrich ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Why is the shape of a singleton array the empty tuple?
On Sun, Mar 7, 2010 at 4:30 AM, Friedrich Romstedt friedrichromst...@gmail.com wrote: First, to David's routine: 2010/3/7 David Goldsmith d.l.goldsm...@gmail.com: def convert_close(arg): arg = N.array(arg) if not arg.shape: arg = N.array((arg,)) if arg.size: t = N.array([0 if N.allclose(temp, 0) else temp for temp in arg]) if len(t.shape) - 1: return N.squeeze(t) else: return t else: return N.array() Ok, chaps, let's code: import numpy def convert_close(ndarray, atol = 1e-5, rtol = 1e-8): ndarray_abs = abs(ndarray) mask = (ndarray_abs atol + rtol * ndarray_abs) return ndarray * mask python -i close.py a = numpy.asarray([1e-6]) convert_close(a) array([ 0.]) a = numpy.asarray([1e-6, 1]) convert_close(a) array([ 0., 1.]) a = numpy.asarray(1e-6) convert_close(a) 0.0 a = numpy.asarray([-1e-6, 1]) convert_close(a) array([ 0., 1.]) Great, thanks! DG ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
[Numpy-discussion] Why is the shape of a singleton array the empty tuple?
x = numpy.array(3) x array(3) x.shape () My question is: why? DG ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Why is the shape of a singleton array the empty tuple?
On Sat, Mar 6, 2010 at 9:37 PM, Ian Mallett geometr...@gmail.com wrote: x = numpy.array(3) x array(3) x.shape () y = numpy.array([3]) y array([3]) y.shape (1,) Ian Thanks, Ian. I already figured out how to make it not so, but I still want to understand the design reasoning behind it being so in the first place (thus the use of the question why (is it so), not how (to make it different)). DG ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Why is the shape of a singleton array the empty tuple?
On Sat, Mar 6, 2010 at 9:46 PM, David Goldsmith d.l.goldsm...@gmail.comwrote: Thanks, Ian. I already figured out how to make it not so, but I still want to understand the design reasoning behind it being so in the first place (thus the use of the question why (is it so), not how (to make it different)). Well, I can't help you with that. I would also ask why this design even exists? Equating an array with a single number doesn't make sense to me. Ian ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Why is the shape of a singleton array the empty tuple?
On Sat, Mar 6, 2010 at 10:26 PM, Ian Mallett geometr...@gmail.com wrote: On Sat, Mar 6, 2010 at 9:46 PM, David Goldsmith d.l.goldsm...@gmail.comwrote: Thanks, Ian. I already figured out how to make it not so, but I still want to understand the design reasoning behind it being so in the first place (thus the use of the question why (is it so), not how (to make it different)). Well, I can't help you with that. I would also ask why this design even exists? Equating an array with a single number doesn't make sense to me. Ian Here's an (unintended) use case: I wanted to convert anything in an array that's close to zero to be zero (and leave the rest as is), but I want it to be robust so that if it receives a scalar, it can work w/ that, too. Here's my (working) code (I'm sure that once Robert sees it, he'll be able to replace it w/ a one-liner): def convert_close(arg): arg = N.array(arg) if not arg.shape: arg = N.array((arg,)) if arg.size: t = N.array([0 if N.allclose(temp, 0) else temp for temp in arg]) if len(t.shape) - 1: return N.squeeze(t) else: return t else: return N.array() At first I wasn't casting arg to be an array upon entry, but I found that if arg is a scalar, my list comprehension failed, so I had choose _some_ sort of sequence to cast scalars to; since arg will typically be an array and that's what I wanted to return as well, it seemed most appropriate to cast incoming scalars to arrays. So I added the arg = N.array(arg) at the beginning (N.array(array) = array, and N.array(non-array seq) does the right thing as well), but the list comprehension still wouldn't work if arg was a scalar upon entry; after many print statements and much interactive experimenting, I finally figured out that this is because the shape of N.array(scalar) is () (and I thence immediately guessed, correctly of course, that N.array((scalar,)) has shape (1,)). So I added the if not arg.shape: to detect and correct for those zero size arrays, and now it works fine, but I'd still like to know _why_ N.array(scalar).shape == () but N.array((scalar,)).shape == (1,). No biggy, just curious. DG ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion