1

Let's say we have a simple 1D ndarray. That is:

import numpy as np
a = np.array([1,2,3,4,5,6,7,8,9,10])

I want to get the first 3 and the last 2 values, so that the output would be [ 1 2 3 9 10].

I have already solved this by merging and concatenating the merged variables as follows :

b= a[:2]
c= a[-2:]
a=np.concatenate([b,c])

However I would like to know if there is a more direct way to achieve this using slices, such as a[:2 and -2:] for instance. As an alternative I already tried this :

a = a[np.r_[:2, -2:]] 

but it not seems to be working. It returns me only the first 2 values that is [1 2] ..

Thanks in advance!

1
  • 2
    r_ requires explicit size information. Practice using it alone. But under the covers it's a concatenate of aranges. So you have to do a concatenate one way or the other. Commented May 7, 2021 at 15:03

2 Answers 2

3

Slicing a numpy array needs to be continuous AFAIK. The np.r_[-2:] does not work because it does not know how big the array a is. You could do np.r_[:2, len(a)-2:len(a)], but this will still copy the data since you are indexing with another array.

If you want to avoid copying data or doing any concatenation operation you could use np.lib.stride_tricks.as_strided:

ds = a.dtype.itemsize
np.lib.stride_tricks.as_strided(a, shape=(2,2), strides=(ds * 8, ds)).ravel()

Output:

array([ 1,  2,  9, 10])

But since you want the first 3 and last 2 values the stride for accessing the elements will not be equal. This is a bit trickier, but I suppose you could do:

np.lib.stride_tricks.as_strided(a, shape=(2,3), strides=(ds * 8, ds)).ravel()[:-1]

Output:

array([ 1,  2,  3,  9, 10])

Although, this is a potential dangerous operation because the last element is reading outside the allocated memory.

In afterthought, I cannot find out a way do this operation without copying the data somehow. The numpy ravel in the code snippets above is forced to make a copy of the data. If you can live with using the shapes (2,2) or (2,3) it might work in some cases, but you will only have reading permission to a strided view and this should be enforced by setting the keyword writeable=False.

Sign up to request clarification or add additional context in comments.

1 Comment

You are right, I try to avoid copying data somehow! Thank you for your detailed answer, I really appreciate it.
1

You could try to access the elements with a list of indices.

import numpy as np
a = np.array([1,2,3,4,5,6,7,8,9,10])
b = a[[0,1,2,8,9]] # b should now be array([ 1,  2,  3,  9, 10])

Obviously, if your array is too long, you would not want to type out all the indices. Thus, you could build the inner index list from for loops. Something like that:

index_list = [i for i in range(3)] + [i for i in range(8, 10)]
b = a[index_list] # b should now be array([ 1,  2,  3,  9, 10])

Therefore, as long as you know where your desired elements are, you can access them individually.

1 Comment

But this doesn't save effort or time. b is still a new array with its own data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.