[Numpy-discussion] Use-case for np.choose
Sun Nov 8 02:57:32 CST 2009
2009/11/8 David Goldsmith <firstname.lastname@example.org>:
> On Sat, Nov 7, 2009 at 11:59 PM, Anne Archibald <email@example.com>
>> 2009/11/7 David Goldsmith <firstname.lastname@example.org>:
>> > So in essence, at least as it presently functions, the shape of 'a'
>> > *defines* what the individual choices are within 'choices`, and if
>> > 'choices'
>> > can't be parsed into an integer number of such individual choices,
>> > that's
>> > when an exception is raised?
>> Um, I don't think so.
>> Think of it this way: you provide np.choose with a selector array, a,
>> and a list (not array!) [c0, c1, ..., cM] of choices. You construct an
>> output array, say r, the same shape as a (no matter how many
>> dimensions it has).
> Except that I haven't yet seen a working example with 'a' greater than 1-D,
> Josef's last two examples notwithstanding; or is that what you're saying is
> the bug.
There's nothing magic about A being one-dimensional.
C = np.random.randn(2,3,5)
A = (C>-1).astype(int) + (C>0).astype(int) + (C>1).astype(int)
R = np.choose(A, (-1, -C, C, 1))
Requv = np.minimum(np.abs(C),1)
"""Return a function whose value is the minimum of those of functions"""
fXs = [f(X) for f in functions]
A = np.argmin(fXs, axis=0)
so e.g. np.abs is -wedge(lambda X: X, lambda X: -X)
This works no matter what shape of X the user supplies - so a wedged
function can be somewhat ufunclike - by making A the same shape.
>> The (i0, i1, ..., iN) element of the output array
>> is obtained by looking at the (i0, i1, ..., iN) element of a, which
>> should be an integer no larger than M; say j. Then r[i0, i1, ..., iN]
>> = cj[i0, i1, ..., iN]. That is, each element of the selector array
>> determines which of the choice arrays to pull the corresponding
>> element from.
> That's pretty clear (thanks for doing my work for me). ;-), Yet, see above.
>> For example, suppose that you are processing an array C, and have
>> constructed a selector array A the same shape as C in which a value is
>> 0, 1, or 2 depending on whether the C value is too small, okay, or too
>> big respectively. Then you might do something like:
>> C = np.choose(A, [-inf, C, inf])
>> This is something you might want to do no matter what shape A and C
>> have. It's important not to require that the choices be an array of
>> choices, because they often have quite different shapes (here, two are
>> scalars) and it would be wasteful to broadcast them up to the same
>> shape as C, just to stack them.
> OK, that's a pretty generic use-case, thanks; let me see if I understand it
> correctly: A is some how created independently with a 0 everywhere C is too
> small, a 1 everywhere C is OK, and a 2 everywhere C is too big; then
> np.choose(A, [-inf, C, inf]) creates an array that is -inf everywhere C is
> too small, inf everywhere C is too large, and C otherwise (and since -inf
> and inf are scalars, this implies broadcasting of these is taking place).
> This is what you're asserting *should* be the behavior. So, unless there is
> disagreement about this (you yourself said the opposite viewpoint might
> rationally be held) np.choose definitely presently has a bug, namely, the
> index array can't be of arbitrary shape.
There seems to be some disagreement between versions, but both Josef
and I find that the index array *can* be arbitrary shape. In numpy
1.2.1 I find that all the choose items must be the same shape as it,
which I think is a bug.
What I suggested might be okay was if the index array was not
broadcasted, so that the outputs always had exactly the same shape as
the index array. But upon reflection it's useful to be able to use a
1-d array to select rows from a set of matrices, so I now think that
all of A and the elements of choose should be broadcast to the same
shape. This seems to be what Josef observes in his version of numpy,
so maybe there's nothing to do.
>> NumPy-Discussion mailing list
> NumPy-Discussion mailing list
More information about the NumPy-Discussion