10

Suppose you have the following numpy array,

>>> x = numpy.array([0,1,2,3,4,5,6,7,8,9,10])

and you want to extract a new numpy array consisting of only the first three (3) and last four (4) elements, i.e.,

>>> y = x[something]
>>> print y
[0 1 2 7 8 9 10]

Is this possible? I know that to extract the first three numbers you simply do x[:3] and to extract the last four you do x[-4:], but is there a simple way of extracting all that in a simple slice? I know this can be done by, e.g., appending both calls,

 >>> y = numpy.append(x[:3],x[-4:])  

but I was wondering if there is some simple little trick to do it in a more direct, pythonic way, without having to reference x again (i.e., I first thought that maybe x[-4:3] could work but I realized immediately that it didn't made sense).

1
  • The question is similar to this one, but the proposed solutions there won't work for newer numpy versions so it's probably not relevant anymore. Still might be interesting: stackoverflow.com/questions/13525266/… Commented Feb 9, 2015 at 15:04

4 Answers 4

4

I think you should use index arrays.

indices = list(range(3))+list(range(-4,0))
y = x[indices]

You can probably drop list casts (not sure because python 3 changed the behaviour a bit). Or you could use numpy range genreators.

Edit: not sure why the downvote, cause it works:

import numpy
x = numpy.array([0,1,2,3,4,5,6,7,8,9,10])
indices = list(range(3))+list(range(-4,0))
y = x[indices]
print(y)
Sign up to request clarification or add additional context in comments.

2 Comments

Yeah, actually is the same thing that occurred to me after watching @mgilson answer (see the comments). Maybe if you add what we commented in that post regarding the use of list around the range I could accept this as the best answer :).
I was typing my answer before seeing comments, I wanted to make it with "dynamic" ranges, and link to the docs.
4

A simple slice probably won't work. You can use numpy's extended slicing:

>>> import numpy as np
>>> a = np.arange(10)
>>> something = [0, 1, 2, -4, -3, -2, -1]
>>> a[something] 
array([0, 1, 2, 6, 7, 8, 9])

Notice I passed in a list of indices that I wanted to take from the original array ...

Frankly though, your solution with np.append is likely just as good...

4 Comments

It could seem like the same, but now that I see your example, I think that an elegant way of doing the same could be: something = range(0,3) + range(-4,0,1). So a general way of slicing the first n elements and the last m elements would be: something = range(0,n) + range(-m,0,1)!
Be careful with adding range together, in Python 3 they're range objects, not lists, and so you'll get a TypeError.
Hi @Ffisegydd; thanks for the input. This means that a more version independant way of doing this would be something = list(range(0,n)) + list(range(-m,0,1))?
Yeah that should be fine :)
1
np.arange(11)[np.r_[0:3,7:11]]
# array([ 0,  1,  2,  7,  8,  9, 10])

np.r_ is a function, actually an indexable object, in numpy/lib/index_tricks. It takes multiple slices, or indexes, and concatenates them into one indexing array.

np.r_[0:3,7:11]
# array([ 0,  1,  2,  7,  8,  9, 10])

Or borrowing from luk32s answer, a negative slice works:

a[np.r_[:3,-4:0]]

An alternative to splicing the 2 parts is to delete the middle. s_ lets you use slice notation inside the function.

np.delete(np.arange(11),np.s_[3:7])
# array([ 0,  1,  2,  7,  8,  9, 10])

Look at the code for the .lib.index_tricks, delete, and insert functions for more ideas on how to construct index arrays from multiple pieces.

Sometimes a boolean index is convenient. Make it all True or False, and flip selected elements.

i = np.ones(a.shape,dtype='bool')
i[3:7] = False
a[i]

Comments

1

These days one can use the built-in function np.setdiff1d() like so:

import numpy as np


x = np.asarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
x_cut_out = np.asarray([3, 4, 5, 6])

x_new = np.setdiff1d(
    ar1=x,
    ar2=x_cut_out
)

This returns the unique values in x that are not in x_cut_out.

>>> print(x_new)
[ 0  1  2  7  8  9 10]

Comments

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.