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

David Huard david.huard at gmail.com
Fri Jan 29 14:58:52 EST 2010


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))

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
>



More information about the NumPy-Discussion mailing list