[Numpy-discussion] How to get the shape of an array slice without doing it

josef.pktd at gmail.com josef.pktd at gmail.com
Fri Jan 29 15:08:14 EST 2010


On Fri, Jan 29, 2010 at 2:58 PM, David Huard <david.huard at gmail.com> wrote:
> For the record, here is what I came up with.
>
> import numpy as np
>
> def expand_ellipsis(index, ndim):
>    """Replace the ellipsis, real or implied, of an index expression by slices.
>
>    Parameters
>    ----------
>    index : tuple
>      Indexing expression.
>    ndim : int
>      Number of dimensions of the array the index applies to.
>
>    Return
>    ------
>    out : tuple
>      An indexing expression of length `ndim` where the Elipsis are replaced
>      by slices.
>    """
>    n = len(index)
>    index = index + ndim * (slice(None),)
>
>    newindex = []
>    for i in index:
>        try:
>            if i == Ellipsis:
>                newindex.extend((ndim - n + 1)*(slice(None),))
>            else:
>                newindex.append(i)
>        except:
>            newindex.append(i)
>
>    return newindex[:ndim]
>
> def indexedshape(shape, index):
>    """Return the shape of an array sliced by index.
>
>    Parameters
>    ----------
>    shape : tuple
>      Shape of the original array.
>    index : tuple
>      Indexing sequence.
>
>    Return
>    ------
>    out : tuple
>      If array A has shape `shape`, then out = A[index].shape.
>
>    Example
>    -------
>    >>> indexedshape((5,4,3,2), (Ellipsis, 0))
>    (5,4,3)
>    >>> indexedshape((5,4,3,2), (slice(None, None, 2), 2, [1,2],
> [True, False]))
>    """
>    index = expand_ellipsis(index, len(shape))
>    out = []
>    for s, i in zip(shape,index):
>        if type(i) == slice:
>            start, stop, stride = i.indices(s)
>            out.append(int(np.ceil((stop-start)*1./stride)))
>        elif np.isscalar(i):
>            pass
>        elif getattr(i, 'dtype', None) == np.bool:
>            out.append(i.sum())
>        else:
>            out.append(len(i))
>
>    return tuple(out)
>
>
> def test_indexedshape():
>    from numpy.testing import assert_equal as eq
>    s = (6,5,4,3)
>    a = np.empty(s)
>    i = np.index_exp[::4, 3:, 0, np.array([True, False, True])]
>    eq(a[i].shape, indexedshape(s, i))
>
>    i = np.index_exp[1::4, 3:, np.array([0,1,2]), ::-1]
>    eq(a[i].shape, indexedshape(s, i))
>
>    i = (0,)
>    eq(a[i].shape, indexedshape(s, i))
>
>    i = (3, Ellipsis, 0)
>    eq(a[i].shape, indexedshape(s, i))

You did the slice part that I didn't manage, but broadcasting doesn't
work correctly ?

>>> i = np.index_exp[1::4, 3:, np.array([0,1,2])[:,None], ::-1]
>>> i
(slice(1, None, 4), slice(3, None, None), array([[0],
       [1],
       [2]]), slice(None, None, -1))
>>> a[i].shape, indexedshape(s, i)
((2, 2, 3, 1, 3), (2, 2, 3, 3))

>>> i = np.index_exp[1::4, np.array([0,1,2])[None,None,:], np.array([0,1,2])[:,None], ::-1]
>>> i
(slice(1, None, 4), array([[[0, 1, 2]]]), array([[0],
       [1],
       [2]]), slice(None, None, -1))
>>> a[i].shape, indexedshape(s, i)
((2, 1, 3, 3, 3), (2, 1, 3, 3))

Josef

>
> On Fri, Jan 29, 2010 at 1:27 PM,  <josef.pktd at gmail.com> wrote:
>> On Fri, Jan 29, 2010 at 1:03 PM, Keith Goodman <kwgoodman at gmail.com> wrote:
>>> On Fri, Jan 29, 2010 at 9:53 AM,  <josef.pktd at gmail.com> wrote:
>>>> I forgot about ellipsis, since I never use them,
>>>> replace ellipsis by [slice(None)]*ndim or something like this
>>>>
>>>> I don't know how to access an ellipsis directly, is it even possible
>>>> to construct an index list that contains an ellipsis?
>>>> There is an object for it but I never looked at it.
>>>
>>> I haven't been following the discussion and I don't understand your
>>> question and in a moment I will accidentally hit send...
>>>
>>>>> class eli(object):
>>>   ...:
>>>   ...:         def __init__(self):
>>>   ...:             pass
>>>   ...:
>>>   ...:     def __getitem__(self, index):
>>>   ...:             print index
>>>   ...:
>>>
>>>>> x[...]
>>> Ellipsis
>>>>> x[...,1]
>>> (Ellipsis, 1)
>>>
>>> Ellipsis is a python class. Built in, no need to import.
>>
>> thanks, this makes it possible to construct index lists with Ellipsis,
>> but it showed that my broadcast idea doesn't work this way
>>
>> Travis explained last year how slices and broadcasting are used for
>> indexing, and it's quite a bit more complicated than this.
>>
>> Sorry for jumping in too fast.
>>
>> Josef
>>
>>>>> indi= (slice(2,5),Ellipsis, np.arange(3)[:,None])
>>>>> ind2 = []
>>>>> for i in indi:
>>        if not i is Ellipsis: ind2.append(i)
>>        else: ind2.extend([slice(None)]*2)
>>
>>
>>>>> ind2
>> [slice(2, 5, None), slice(None, None, None), slice(None, None, None),
>> array([[0],
>>       [1],
>>       [2]])]
>>>>> np.broadcast(*ind2).shape
>> (3, 1)
>>
>>
>>
>>> _______________________________________________
>>> 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