[Numpy-discussion] How to get the shape of an array slice without doing it
David Huard
david.huard@gmail....
Fri Jan 29 13:58:52 CST 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@gmail.com> wrote:
> On Fri, Jan 29, 2010 at 1:03 PM, Keith Goodman <kwgoodman@gmail.com> wrote:
>> On Fri, Jan 29, 2010 at 9:53 AM, <josef.pktd@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@scipy.org
>> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
More information about the NumPy-Discussion
mailing list