ndarrays can be indexed using the standard Pythonx[obj] syntax, wherex is the array andobj the selection.There are three kinds of indexing available: field access, basicslicing, advanced indexing. Which one occurs depends onobj.
Note
In Python,x[(exp1,exp2,...,expN)] is equivalent tox[exp1,exp2,...,expN]; the latter is just syntactic sugarfor the former.
Basic slicing extends Python’s basic concept of slicing to Ndimensions. Basic slicing occurs whenobj is aslice object(constructed bystart:stop:step notation inside of brackets), aninteger, or a tuple of slice objects and integers.Ellipsisandnewaxis objects can be interspersed with these aswell.
Deprecated since version 1.15.0:In order to remain backward compatible with a common usage inNumeric, basic slicing is also initiated if the selection object isany non-ndarray and non-tuple sequence (such as alist) containingslice objects, theEllipsis object, or thenewaxisobject, but not for integer arrays or other embedded sequences.
The simplest case of indexing withN integers returns anarrayscalar representing the corresponding item. As inPython, all indices are zero-based: for thei-th indexn_i,the valid range is0 \le n_i < d_i whered_i is thei-th element of the shape of the array. Negative indices areinterpreted as counting from the end of the array (i.e., ifn_i < 0, it meansn_i + d_i).
All arrays generated by basic slicing are alwaysviewsof the original array.
The standard rules of sequence slicing apply to basic slicing on aper-dimension basis (including using a step index). Some usefulconcepts to remember include:
The basic slice syntax isi:j:k wherei is the starting index,j is the stopping index, andk is the step (k\neq0).This selects them elements (in the corresponding dimension) withindex valuesi,i + k, …,i + (m - 1) k wherem = q + (r\neq0) andq andr are the quotient and remainderobtained by dividingj - i byk:j - i = q k + r, so thati + (m - 1) k < j.
Example
>>>x=np.array([0,1,2,3,4,5,6,7,8,9])>>>x[1:7:2]array([1, 3, 5])
Negativei andj are interpreted asn + i andn + j wheren is the number of elements in the corresponding dimension.Negativek makes stepping go towards smaller indices.
Example
>>>x[-2:10]array([8, 9])>>>x[-3:3:-1]array([7, 6, 5, 4])
Assumen is the number of elements in the dimension beingsliced. Then, ifi is not given it defaults to 0 fork > 0 andn - 1 fork < 0 . Ifj is not given it defaults ton fork > 0and-n-1 fork < 0 . Ifk is not given it defaults to 1. Note that:: is the same as: and means select all indices along thisaxis.
Example
>>>x[5:]array([5, 6, 7, 8, 9])
If the number of objects in the selection tuple is less thanN , then: is assumed for any subsequent dimensions.
Example
>>>x=np.array([[[1],[2],[3]],[[4],[5],[6]]])>>>x.shape(2, 3, 1)>>>x[1:2]array([[[4], [5], [6]]])
Ellipsis expand to the number of: objects needed tomake a selection tuple of the same length asx.ndim. There mayonly be a single ellipsis present.
Example
>>>x[...,0]array([[1, 2, 3], [4, 5, 6]])
Eachnewaxis object in the selection tuple serves to expandthe dimensions of the resulting selection by one unit-lengthdimension. The added dimension is the position of thenewaxisobject in the selection tuple.
Example
>>>x[:,np.newaxis,:,:].shape(2, 1, 3, 1)
An integer,i, returns the same values asi:i+1except the dimensionality of the returned object is reduced by1. In particular, a selection tuple with thep-thelement an integer (and all other entries:) returns thecorresponding sub-array with dimensionN - 1. IfN = 1then the returned object is an array scalar. These objects areexplained inScalars.
If the selection tuple has all entries: except thep-th entry which is a slice objecti:j:k,then the returned array has dimensionN formed byconcatenating the sub-arrays returned by integer indexing ofelementsi,i+k, …,i + (m - 1) k < j,
Basic slicing with more than one non-: entry in the slicingtuple, acts like repeated application of slicing using a singlenon-: entry, where the non-: entries are successively taken(with all other non-: entries replaced by:). Thus,x[ind1,...,ind2,:] acts likex[ind1][...,ind2,:] under basicslicing.
Warning
The above isnot true for advanced indexing.
You may use slicing to set values in the array, but (unlike lists) youcan never grow the array. The size of the value to be set inx[obj]=value must be (broadcastable) to the same shape asx[obj].
Note
Remember that a slicing tuple can always be constructed asobjand used in thex[obj] notation. Slice objects can be used inthe construction in place of the[start:stop:step]notation. For example,x[1:10:5,::-1] can also be implementedasobj=(slice(1,10,5),slice(None,None,-1));x[obj] . Thiscan be useful for constructing generic code that works on arraysof arbitrary dimension.
Advanced indexing is triggered when the selection object,obj, is anon-tuple sequence object, anndarray (of data type integer or bool),or a tuple with at least one sequence object or ndarray (of data typeinteger or bool). There are two types of advanced indexing: integerand Boolean.
Advanced indexing always returns acopy of the data (contrast withbasic slicing that returns aview).
Warning
The definition of advanced indexing means thatx[(1,2,3),] isfundamentally different thanx[(1,2,3)]. The latter isequivalent tox[1,2,3] which will trigger basic selection whilethe former will trigger advanced indexing. Be sure to understandwhy this occurs.
Also recognize thatx[[1,2,3]] will trigger advanced indexing,whereas due to the deprecated Numeric compatibility mentioned above,x[[1,2,slice(None)]] will trigger basic slicing.
Integer array indexing allows selection of arbitrary items in the arraybased on theirN-dimensional index. Each integer array represents a numberof indexes into that dimension.
When the index consists of as many integer arrays as the array being indexedhas dimensions, the indexing is straight forward, but different from slicing.
Advanced indexes always arebroadcast anditerated asone:
result[i_1,...,i_M]==x[ind_1[i_1,...,i_M],ind_2[i_1,...,i_M],...,ind_N[i_1,...,i_M]]
Note that the result shape is identical to the (broadcast) indexing arrayshapesind_1,...,ind_N.
Example
From each row, a specific element should be selected. The row index is just[0,1,2] and the column index specifies the element to choose for thecorresponding row, here[0,1,0]. Using both together the taskcan be solved using advanced indexing:
>>>x=np.array([[1,2],[3,4],[5,6]])>>>x[[0,1,2],[0,1,0]]array([1, 4, 5])
To achieve a behaviour similar to the basic slicing above, broadcasting can beused. The functionix_ can help with this broadcasting. This is bestunderstood with an example.
Example
From a 4x3 array the corner elements should be selected using advancedindexing. Thus all elements for which the column is one of[0,2] andthe row is one of[0,3] need to be selected. To use advanced indexingone needs to select all elementsexplicitly. Using the method explainedpreviously one could write:
>>>x=array([[0,1,2],...[3,4,5],...[6,7,8],...[9,10,11]])>>>rows=np.array([[0,0],...[3,3]],dtype=np.intp)>>>columns=np.array([[0,2],...[0,2]],dtype=np.intp)>>>x[rows,columns]array([[ 0, 2], [ 9, 11]])
However, since the indexing arrays above just repeat themselves,broadcasting can be used (compare operations such asrows[:,np.newaxis]+columns) to simplify this:
>>>rows=np.array([0,3],dtype=np.intp)>>>columns=np.array([0,2],dtype=np.intp)>>>rows[:,np.newaxis]array([[0], [3]])>>>x[rows[:,np.newaxis],columns]array([[ 0, 2], [ 9, 11]])
This broadcasting can also be achieved using the functionix_:
>>>x[np.ix_(rows,columns)]array([[ 0, 2], [ 9, 11]])
Note that without thenp.ix_ call, only the diagonal elements wouldbe selected, as was used in the previous example. This difference is themost important thing to remember about indexing with multiple advancedindexes.
When there is at least one slice (:), ellipsis (...) ornp.newaxisin the index (or the array has more dimensions than there are advanced indexes),then the behaviour can be more complicated. It is like concatenating theindexing result for each advanced index element
In the simplest case, there is only asingle advanced index. A singleadvanced index can for example replace a slice and the result array will bethe same, however, it is a copy and may have a different memory layout.A slice is preferable when it is possible.
Example
>>>x[1:2,1:3]array([[4, 5]])>>>x[1:2,[1,2]]array([[4, 5]])
The easiest way to understand the situation may be to think interms of the result shape. There are two parts to the indexing operation,the subspace defined by the basic indexing (excluding integers) and thesubspace from the advanced indexing part. Two cases of index combinationneed to be distinguished:
x[arr1,:,arr2].x[...,arr1,arr2,:] butnotx[arr1,:,1]since1 is an advanced index in this regard.In the first case, the dimensions resulting from the advanced indexingoperation come first in the result array, and the subspace dimensions afterthat.In the second case, the dimensions from the advanced indexing operationsare inserted into the result array at the same spot as they were in theinitial array (the latter logic is what makes simple advanced indexingbehave just like slicing).
Example
Supposex.shape is (10,20,30) andind is a (2,3,4)-shapedindexingintp array, thenresult=x[...,ind,:] hasshape (10,2,3,4,30) because the (20,)-shaped subspace has beenreplaced with a (2,3,4)-shaped broadcasted indexing subspace. Ifwe leti, j, k loop over the (2,3,4)-shaped subspace thenresult[...,i,j,k,:]=x[...,ind[i,j,k],:]. This exampleproduces the same result asx.take(ind,axis=-2).
Example
Letx.shape be (10,20,30,40,50) and supposeind_1andind_2 can be broadcast to the shape (2,3,4). Thenx[:,ind_1,ind_2] has shape (10,2,3,4,40,50) because the(20,30)-shaped subspace from X has been replaced with the(2,3,4) subspace from the indices. However,x[:,ind_1,:,ind_2] has shape (2,3,4,10,30,50) because thereis no unambiguous place to drop in the indexing subspace, thusit is tacked-on to the beginning. It is always possible to use.transpose() to move the subspaceanywhere desired. Note that this example cannot be replicatedusingtake.
This advanced indexing occurs when obj is an array object of Booleantype, such as may be returned from comparison operators. A singleboolean index array is practically identical tox[obj.nonzero()] where,as described above,obj.nonzero() returns atuple (of lengthobj.ndim) of integer indexarrays showing theTrue elements ofobj. However, it isfaster whenobj.shape==x.shape.
Ifobj.ndim==x.ndim,x[obj] returns a 1-dimensional arrayfilled with the elements ofx corresponding to theTruevalues ofobj. The search order will berow-major,C-style. Ifobj hasTrue values at entries that are outsideof the bounds ofx, then an index error will be raised. Ifobj issmaller thanx it is identical to filling it withFalse.
Example
A common use case for this is filtering for desired element values.For example one may wish to select all entries from an array whichare not NaN:
>>>x=np.array([[1.,2.],[np.nan,3.],[np.nan,np.nan]])>>>x[~np.isnan(x)]array([ 1., 2., 3.])
Or wish to add a constant to all negative elements:
>>>x=np.array([1.,-1.,-2.,3])>>>x[x<0]+=20>>>xarray([ 1., 19., 18., 3.])
In general if an index includes a Boolean array, the result will beidentical to insertingobj.nonzero() into the same positionand using the integer array indexing mechanism described above.x[ind_1,boolean_array,ind_2] is equivalent tox[(ind_1,)+boolean_array.nonzero()+(ind_2,)].
If there is only one Boolean array and no integer indexing array present,this is straight forward. Care must only be taken to make sure that theboolean index hasexactly as many dimensions as it is supposed to workwith.
Example
From an array, select all rows which sum up to less or equal two:
>>>x=np.array([[0,1],[1,1],[2,2]])>>>rowsum=x.sum(-1)>>>x[rowsum<=2,:]array([[0, 1], [1, 1]])
But ifrowsum would have two dimensions as well:
>>>rowsum=x.sum(-1,keepdims=True)>>>rowsum.shape(3, 1)>>>x[rowsum<=2,:]# failsIndexError: too many indices>>>x[rowsum<=2]array([0, 1])
The last one giving only the first elements because of the extra dimension.Comparerowsum.nonzero() to understand this example.
Combining multiple Boolean indexing arrays or a Boolean with an integerindexing array can best be understood with theobj.nonzero() analogy. The functionix_also supports boolean arrays and will work without any surprises.
Example
Use boolean indexing to select all rows adding up to an evennumber. At the same time columns 0 and 2 should be selected with anadvanced integer index. Using theix_ function this can be donewith:
>>>x=array([[0,1,2],...[3,4,5],...[6,7,8],...[9,10,11]])>>>rows=(x.sum(-1)%2)==0>>>rowsarray([False, True, False, True])>>>columns=[0,2]>>>x[np.ix_(rows,columns)]array([[ 3, 5], [ 9, 11]])
Without thenp.ix_ call or only the diagonal elements would beselected.
Or withoutnp.ix_ (compare the integer array examples):
>>>rows=rows.nonzero()[0]>>>x[rows[:,np.newaxis],columns]array([[ 3, 5], [ 9, 11]])
These are some detailed notes, which are not of importance for day to dayindexing (in no particular order):
intp and may differ from thedefault integer array type.intp is the smallest data typesufficient to safely index any array; for advanced indexing it may befaster than other types.x[()] returns ascalar ifx is zero dimensional and a viewotherwise. On the other handx[...] always returns a view....) is present but has no size (i.e. replaces zero:) the result will still always be an array. A view if no advanced indexis present, otherwise a copy.nonzero equivalence for Boolean arrays does not hold for zerodimensional boolean arrays.IndexError israised is undefined (e.g.x[[],[123]] with123 being out of bounds).ndarray.__setitem__ behaviour will call__getitem__ forbasic indexing but not foradvanced indexing. For such a subclass it maybe preferable to callndarray.__setitem__ with abase class ndarrayview on the data. Thismust be done if the subclasses__getitem__ doesnot return views.See also
If thendarray object is a structured array thefieldsof the array can be accessed by indexing the array with strings,dictionary-like.
Indexingx['field-name'] returns a newview to the array,which is of the same shape asx (except when the field is asub-array) but of data typex.dtype['field-name'] and containsonly the part of the data in the specified field. Alsorecord array scalars can be “indexed” this way.
Indexing into a structured array can also be done with a list of field names,e.g.x[['field-name1','field-name2']]. Currently this returns a newarray containing a copy of the values in the fields specified in the list.As of NumPy 1.7, returning a copy is being deprecated in favor of returninga view. A copy will continue to be returned for now, but a FutureWarningwill be issued when writing to the copy. If you depend on the currentbehavior, then we suggest copying the returned array explicitly, i.e. usex[[‘field-name1’,’field-name2’]].copy(). This will work with both past andfuture versions of NumPy.
If the accessed field is a sub-array, the dimensions of the sub-arrayare appended to the shape of the result.
Example
>>>x=np.zeros((2,2),dtype=[('a',np.int32),('b',np.float64,(3,3))])>>>x['a'].shape(2, 2)>>>x['a'].dtypedtype('int32')>>>x['b'].shape(2, 2, 3, 3)>>>x['b'].dtypedtype('float64')
x.flat returns an iterator that will iterateover the entire array (in C-contiguous style with the last indexvarying the fastest). This iterator object can also be indexed usingbasic slicing or advanced indexing as long as the selection object isnot a tuple. This should be clear from the fact thatx.flat is a 1-dimensional view. It can be used for integerindexing with 1-dimensional C-style-flat indices. The shape of anyreturned array is therefore the shape of the integer indexing object.