[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