3

Given a numpy ndarray and an index:

a = np.random.randint(0,4,(2,3,4))
idx = (1,1,1)

is there a clean way of retrieving the 0D subarray of a at idx?

Something equivalent to

a[idx + (None,)].squeeze()

but less hackish?

Note that @filippo's clever

a[idx][...]

is not equivalent. First, it doesn't work for object arrays. But more seriously it does not return a subarray but a new array:

b = a[idx][...]
b[()] = 7
a[idx] == 7
# False
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99

2 Answers2

2

Not sure I understood properly what you want, does this look clean enough?

In [1]: import numpy as np

In [2]: a = np.random.randint(0,4,(2,3,4))
   ...: idx = (1,1,1)
   ...: 

In [3]: a[idx]
Out[3]: 2

In [4]: a[idx][...]
Out[4]: array(2)

EDIT: note that this returns a copy, not a 0D view of the same array

filippo
  • 5,197
  • 2
  • 21
  • 44
  • Wow, I didn't know that! Thanks! But, alas, it doesn't work with object arrays. I've upated the question. – Paul Panzer Dec 21 '17 at 07:39
  • `a[idx+(Ellipsis,)]` seems to work. It blends both ideas. `a[idx]` for object array returns a `int`. For `int` array it returns `np.int32`. That is already a close cousin to a 0d array. Look at its methods and attributes. – hpaulj Dec 21 '17 at 07:50
  • @hpaulj Yes! That's it. I think that's worth an answer. - Close cousin, yes, but it's mutability and sharing its data with the original array I'm after. – Paul Panzer Dec 21 '17 at 07:55
  • Uh, you're right, advanced indexing always copies if I recall correctly. Can't come up with anything better than @hpaulj though, please add an answer! – filippo Dec 21 '17 at 07:58
2
b = a[idx+(Ellipsis,)]

I'm testing on one machine and writing this a tablet, so can't give my usual verification code.

Perhaps the best documentation explanation (or statement of fact) is:

https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html#detailed-notes

When an ellipsis (...) is present but has no size (i.e. replaces zero :) the result will still always be an array. A view if no advanced index is present, otherwise a copy.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Funny, that's actually another counter example to my [very first post](https://stackoverflow.com/q/41233678/7207392) on SO and guess who answered that one ... – Paul Panzer Dec 21 '17 at 08:09
  • Ok, let me challenge you to explain _why_ this actually works! – Paul Panzer Dec 21 '17 at 08:22
  • In `a[1,1,1,...]`, the `Ellipsis` means fill in the remaining dimensions, like a `[:]*`. That can be 2, 1 or in this case 0. I found a documentation note that states what happens even if it doesn't exactly explain the action. – hpaulj Dec 21 '17 at 18:49
  • Thanks! That's a complete answer. – Paul Panzer Dec 21 '17 at 19:24