1

Is there a way to do multiple indexing in a numpy array as described below?

arr=np.array([55, 2, 3, 4, 5, 6, 7, 8, 9])
arr[np.arange(0,2):np.arange(5,7)]

output:
IndexError: too many indices for array

Desired output:
array([55,2,3,4,5],[2,3,4,5,6])

This problem might be similar to calculating a moving average over an array (but I want to do it without any function that is provided).

Nickpick
  • 6,163
  • 16
  • 65
  • 116
  • Do you want something like `np.vstack((arr[np.arange(0, 6)], arr[np.arange(1, 7)]))`? – mgilson Oct 31 '16 at 15:40
  • Yes that would be the output, but the shortcut doesn't count as in the real world arr will contain data that cannot be reproduced sith an np.arrange. I changed the question to make it clear. – Nickpick Oct 31 '16 at 15:42
  • I'm not sure how `np.arange(0,2)` relates to your desired output? – njzk2 Oct 31 '16 at 15:46
  • It's the starting index. 0 and then 1, while the ending index is 5 and then 6. – Nickpick Oct 31 '16 at 15:47
  • So, the range (stop - start), which is `5` in the sample case would be the same for all intervals? – Divakar Oct 31 '16 at 15:51
  • Yes it would be identical, I assume it would have to be, otherwise, the matrix has different lengths which is not allowed – Nickpick Oct 31 '16 at 15:53
  • Shouldn't the second row be `[ 3, 4, 5, 6, 7]` instead? – Divakar Oct 31 '16 at 15:56
  • @nickpick -- I'm really not sure what you're trying to say here ... My `vstack` "solution" gives your desired output with the updated `arr` too... – mgilson Oct 31 '16 at 15:56
  • Also note that if you don't need to index using crazy arrays, `np.vstack((arr[:6], arr[1:7]))` is easier to type, easier to understand and likely more performant. – mgilson Oct 31 '16 at 15:58
  • @mgilson Yes in this case the solution is correct but it is not general enough. It works only with a small matrix size as you have to manually stack them together. arr[np.arange(0,5):np.arange(5,10)] would be quite laborious already and it wouldn't work for very large arrays. – Nickpick Oct 31 '16 at 16:00
  • @Divakar No, the second row has a starting index of 1: `np.arange(0,2) Out[41]: array([0, 1])` – Nickpick Oct 31 '16 at 16:02
  • 1
    You don't need to manually stack them together ... You just need to generate the arrays that you want to stack together. Another, more general option is to do: `np.vstack([arr[slice(start, stop)] for start, stop in zip(np.arange(0, 2), np.arange(5, 7))])` – mgilson Oct 31 '16 at 16:12
  • http://stackoverflow.com/questions/37984214/pure-numpy-expression-for-selecting-same-length-subarrays-with-different-startin encountered the same error, from trying to use arrays (or lists) as inputs to a slice. In general it's a question of how to generate multiple indexing ranges. – hpaulj Oct 31 '16 at 18:24

1 Answers1

1

Here's an approach using strides -

start_index = np.arange(0,2)
L = 5     # Interval length
n = arr.strides[0]
strided = np.lib.stride_tricks.as_strided
out = strided(arr[start_index[0]:],shape=(len(start_index),L),strides=(n,n))

Sample run -

In [976]: arr
Out[976]: array([55, 52, 13, 64, 25, 76, 47, 18, 69, 88])

In [977]: start_index
Out[977]: array([2, 3, 4])

In [978]: L = 5

In [979]: out
Out[979]: 
array([[13, 64, 25, 76, 47],
       [64, 25, 76, 47, 18],
       [25, 76, 47, 18, 69]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Can you clarify if for n = arr.strides[0] you always take the [0] element or if there can be a difference depending in what dimension the stride goes? – Nickpick Nov 02 '16 at 15:57
  • @nickpick Well arr.strides give us a tuple of strides along all dims. Since we are working with 1D array, we just need the strides along the first axis, so we get the first elem of that tuple with `[0]`. If that answers your question? – Divakar Nov 02 '16 at 16:09
  • 1
    @nickpick See here for an example on using two-dimensional strides - http://stackoverflow.com/a/40367540/3293881 – Divakar Nov 02 '16 at 16:12