[Numpy-discussion] Use-case for np.choose

Anne Archibald peridot.faceted at gmail.com
Sun Nov 8 03:13:46 EST 2009


2009/11/8  <josef.pktd at gmail.com>:
> On Sat, Nov 7, 2009 at 7:53 PM, David Goldsmith <d.l.goldsmith at gmail.com> wrote:
>> Thanks, Anne.
>>
>> On Sat, Nov 7, 2009 at 1:32 PM, Anne Archibald <peridot.faceted at gmail.com>
>> wrote:
>>>
>>> 2009/11/7 David Goldsmith <d.l.goldsmith at gmail.com>:
>>
>> <snip>
>>
>>>
>>> > Also, my experimenting suggests that the index array ('a', the first
>>> > argument in the func. sig.) *must* have shape (choices.shape[-1],) -
>>> > someone
>>> > please let me know ASAP if this is not the case, and please furnish me
>>> > w/ a
>>> > counterexample because I was unable to generate one myself.
>>>
>>> It seems like a and each of the choices must have the same shape
>>
>> 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?
>>
>>>
>>> (with
>>>
>>> the exception that choices acn be scalars), but I would consider this
>>> a bug.
>>
>> OK, then we definitely need more people to opine on this, because, if the
>> the two don't match, our established policy is to document *desired*
>> behavior, not extant behavior (and file a bug ticket).
>>
>>>
>>> Really, a and all the choices should be broadcast to the same
>>> shape. Or maybe it doesn't make sense to broadcast a - it could be
>>
>> Thus begging the question: does anyone actually have an extant, specific
>> use-case?
>>
>>>
>>> valuable to know that the result is always exactly the same shape as a
>>> - but broadcasting all the choice arrays presents an important
>>> improvement of choose over fancy indexing.
>>
>> Then perhaps we need either another function, or a flag specifying which
>> behavior this one should exhibit.
>>
>>>
>>> There's a reason choose
>>> accepts a sequence of arrays as its second argument, rather than a
>>> higher-dimensional array.
>>
>> And that reason is probably supposed to be transparent above, but I've
>> confused it by this point, so can you please reiterate it here, in so many
>> words. :-)
>
> >From looking at a few special cases, I think that full broadcasting rules apply.
> First a and all choice array are broadcast to the same shape,
> then the selection is done according to the elements of (the broadcasted) a.
>
> For broadcasting it doesn't matter whether they are scalars or 1d or 2d or
> a 2d single column array. (I haven't tried more than 2 dimensions)

This must have changed since 1.2.1, since I get ValueError: too many
dimensions for all those examples. (Though the 1.2.1 docs claim
broadcasting.)

> The examples look a bit messy, but broadcasting is relatively straightforward.
>
> (I think, np.where is a bit easier to use because `a` is just a
> condition and doesn't
> require an index array)

Well, a condition *is* an index array, it is just restricted to the
values 0 and 1. But I agree it's not so natural to construct an index
array with more values. I guess you could do something like:

A = (C>-1) + (C>0) + (C>1)
B = np.choose(A, (1, -C, C, 1))

But that's one of those magical numpy expressions that make the reader
stop and ask "how on earth does that work?" For further bewilderment
you'd make it computed:

A = np.sum(C[...,None]>transition_values, axis=-1)
B = np.choose(A, [piece(C) for piece in piecewise_pieces])

Anne

> Josef
>
>>>> np.choose(1, (3,4))
> 4
>>>> np.choose(0, (3,4))
> 3
>>>> np.choose(0, (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 0, 0, 0],
>       [1, 1, 1, 1],
>       [2, 2, 2, 2]])
>>>> np.choose(2, (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 0, 0, 0],
>       [0, 0, 0, 0],
>       [0, 0, 0, 0]])
>>>> np.choose(1, (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 1, 2, 3],
>       [0, 1, 2, 3],
>       [0, 1, 2, 3]])
>>>> np.choose([1,2,0,0], (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 0, 0, 0],
>       [0, 0, 1, 1],
>       [0, 0, 2, 2]])
>>>> np.choose(np.array([[1,2,0,0]]), (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 0, 0, 0],
>       [0, 0, 1, 1],
>       [0, 0, 2, 2]])
>>>> np.choose(np.array([[1,2,0]]).T, (np.arange(3)[:,None],np.arange(4),0))
> array([[0, 1, 2, 3],
>       [0, 0, 0, 0],
>       [2, 2, 2, 2]])
>
>
>
>
>>
>> Thanks again,
>>
>> DG
>>>
>>> Anne
>>>
>>> > Thanks,
>>> >
>>> > DG
>>> >
>>> > _______________________________________________
>>> > NumPy-Discussion mailing list
>>> > NumPy-Discussion at scipy.org
>>> > http://mail.scipy.org/mailman/listinfo/numpy-discussion
>>> >
>>> >
>>> _______________________________________________
>>> NumPy-Discussion mailing list
>>> NumPy-Discussion at scipy.org
>>> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>>
>>
>> _______________________________________________
>> NumPy-Discussion mailing list
>> NumPy-Discussion at scipy.org
>> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>>
>>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>



More information about the NumPy-Discussion mailing list