1

I am failing to understand how the function slice() relates to the usual Numpy indexing notation.

test = np.random.rand(4,4,4)
test[:,0:1,2]
>>> array([[0.73897606],
         [0.68005618],
         [0.32831257],
         [0.36882484]])

but I cannot see what is about to go on now

test[slice(None),slice(0,1),slice(2,3)]
>>>> array([[[0.73897606]],

           [[0.68005618]],

           [[0.32831257]],

           [[0.36882484]]])

Some experiments seem to confirm that slice(None) is equivalent to :, slice(0,1) is equivalent to 0:1, but slice(2,3) is equivalent to 2, as an index.

How to describe the [:,0:1,2] slicing using the slice() function?

Could somebody please give us a hint? I also do not get where the shape of the second output comes from, many thanks

EDIT - ADDITIONAL BACKGROUND

What I would like to be able to do is dynamically slice an array, given an input. For example, given an array S with shape (10,10,10,10), the user might select two variables to plot over, keeping the other two fixed at a selected location. For example, (surface)plot the first and third, keeping the second and fourth at indeces say (2,3). I can pass then the array S[:,2,:,3].

Following the answer in Dynamically slice an array, I though I would have something like

axis_to_plot_1 = 0
axis_to_plot_2 = 2
axis_to_slice_1 = 1
index_to_consider_1 = 2
axis_to_slice_2 = 3
index_to_consider_2 = 3
slc = [slice(None)] * len(S.shape)
slc[axis_to_slice_1] = slice(index_to_consider_1, index_to_consider_1 +1)
slc[axis_to_slice_2] = slice(index_to_consider_2, index_to_consider_2+1)

this would solve my issue, I could slice() for both the : (variable to consider when plotting) and "i" indexing cases (section on remaining dimensions).

How is the above dynamical slicing over two axes best implemented, any ideas please?

user37292
  • 248
  • 2
  • 12
  • 1
    You said: "slice(2,3) is equivalent to 2". That's not true. Carefully check the number of dimensions in `test[slice(2, 3)]` versus `test[2]`. `slice(2, 3)` is still equivalent to `2:3`, which amounts to just one element (along that axis), but in a list, while `2` result in one element on its own. – 9769953 Jul 19 '23 at 09:49
  • 1
    There is no equivalent slice for a simple integer index: `2` is just two; don't use `slice()`. – 9769953 Jul 19 '23 at 09:51
  • thanks a lot, got really fooled on this one. I added some background above of what I was trying to achieve, and why I tried to use slice for a simple integer index. – user37292 Jul 19 '23 at 10:24
  • `np.s_` goes the other direction: `np.s_[:4,2:3,2]` returns `(slice(None, 4, None), slice(2, 3, None), 2)`. So `a:b:c` has a `slice(a,b,c)` equivalent. But scalar `2` is not expressible as a `slice`. In `s_`, it's actually the python interpreter that's parsing the 'a:b:c', and creating the `slice` object. – hpaulj Jul 19 '23 at 15:38

1 Answers1

2

It is not equivalent. 2 is not a slice but an index. A slice will keep the number of dimensions, while an index will remove one.

The equivalence would be:

test[:, 0:1, [2]]

Output:

array([[[0.42475402]],

       [[0.48023367]],

       [[0.95256927]],

       [[0.25481038]]])
mozway
  • 194,879
  • 13
  • 39
  • 75
  • thanks for this, I got badly fooled. I added above some background about what is that I am trying to achieve, if you could have a look that would be great. IF there is no way to use ```slice()``` to reproduce an index, my idea described above fails, thanks a lot – user37292 Jul 19 '23 at 10:23
  • @user37292 as slicing is keeping the dimensions, just make your plotting code use the original dimensions. Otherwise, you can always [`squeeze`](https://numpy.org/doc/stable/reference/generated/numpy.squeeze.html) the array to remove the axes of length one. – mozway Jul 19 '23 at 11:15