np.delete
is not doing anything unique or special. It just returns a copy of the original array with some items missing. Most of the code just interprets the inputs in preparation to make this copy.
What you are asking about is the obj
parameter
obj : slice, int or array of ints
In simple terms, np.s_
lets you supply a slice using the familiar :
syntax. The x:y
notation cannot be used as a function parameter.
Let's try your alternatives (you allude to these in results and errors, but they are buried in the text):
In [213]: x=np.arange(10)*2 # some distinctive values
In [214]: np.delete(x, np.s_[3:6])
Out[214]: array([ 0, 2, 4, 12, 14, 16, 18])
So delete
with s_
removes a range of values, namely 6 8 10
, the 3rd through 5th ones.
In [215]: np.delete(x, [3:6])
File "<ipython-input-215-0a5bf5cc05ba>", line 1
np.delete(x, [3:6])
^
SyntaxError: invalid syntax
Why the error? Because [3:4]
is an indexing expression. np.delete
is a function. Even s_[[3:4]]
has problems. np.delete(x, 3:6)
is also bad, because Python only accepts the :
syntax in an indexing context, where it automatically translates it into a slice
object. Note that is is a syntax error
, something that the interpreter catches before doing any calculations or function calls.
In [216]: np.delete(x, slice(3,6))
Out[216]: array([ 0, 2, 4, 12, 14, 16, 18])
A slice
works instead of s_
; in fact that is what s_
produces
In [233]: np.delete(x, [3,4,5])
Out[233]: array([ 0, 2, 4, 12, 14, 16, 18])
A list also works, though it works in different way (see below).
In [217]: np.delete(x, x[3:6])
Out[217]: array([ 0, 2, 4, 6, 8, 10, 14, 18])
This works, but produces are different result, because x[3:6]
is not the same as range(3,6)
. Also the np.delete
does not work like the list
delete. It deletes by index, not by matching value.
np.index_exp
fails for the same reason that np.delete(x, (slice(3,6),))
does. 1
, [1]
, (1,)
are all valid and remove one item. Even '1'
, the string, works. delete
parses this argument, and at this level, expects something that can be turned into an integer. obj.astype(intp)
. (slice(None),)
is not a slice, it is a 1 item tuple. So it's handled in a different spot in the delete
code. This is TypeError
produced by something that delete
calls, very different from the SyntaxError
. In theory delete
could extract the slice from the tuple and proceed as in the s_
case, but the developers did not choose to consider this variation.
A quick study of the code shows that np.delete
uses 2 distinct copying methods - by slice and by boolean mask. If the obj
is a slice, as in our example, it does (for 1d array):
out = np.empty(7)
out[0:3] = x[0:3]
out[3:7] = x[6:10]
But with [3,4,5]
(instead of the slice) it does:
keep = np.ones((10,), dtype=bool)
keep[[3,4,5]] = False
return x[keep]
Same result, but with a different construction method. x[np.array([1,1,1,0,0,0,1,1,1,1],bool)]
does the same thing.
In fact boolean indexing or masking like this is more common than np.delete
, and generally just as powerful.
From the lib/index_tricks.py
source file:
index_exp = IndexExpression(maketuple=True)
s_ = IndexExpression(maketuple=False)
They are slighly different versions of the same thing. And both are just convenience functions.
In [196]: np.s_[1:4]
Out[196]: slice(1, 4, None)
In [197]: np.index_exp[1:4]
Out[197]: (slice(1, 4, None),)
In [198]: np.s_[1:4, 5:10]
Out[198]: (slice(1, 4, None), slice(5, 10, None))
In [199]: np.index_exp[1:4, 5:10]
Out[199]: (slice(1, 4, None), slice(5, 10, None))
The maketuple
business applies only when there is a single item, a slice or index.