| Draft for Information Only ContentIndexingBasic Slicing and Indexing
 Warning
 Note
 numpy.newaxis
 Advanced Indexing
 Warning
 Integer array indexing
 Purely integer array indexing
 Example
 Example
 Combining advanced and basic indexing
 Boolean array indexing
 Detailed notes
 Field Access
 Flat Iterator indexing
 Source and Reference
 
    Indexing
        ndarrayscan be indexed using the standard Pythonx[obj]syntax, wherexis the array andobjthe selection. There are three kinds of indexing available: field access, basic slicing, 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 sugar for the former. Basic Slicing and Indexing
            Basic slicing extends Python’s basic concept of slicing to N dimensions. Basic slicing occurs when objis asliceobject (constructed bystart:stop:stepnotation inside of brackets), an integer, or a tuple of slice objects and integers.Ellipsisandnewaxisobjects can be interspersed with these as well. 
            
                Deprecated since version 1.15.0: In order to remain backward compatible with a common usage in Numeric, basic slicing is also initiated if the selection object is any non-ndarray and non-tuple sequence (such as a list) containingsliceobjects, theEllipsisobject, or thenewaxisobject, but not for integer arrays or other embedded sequences. 
       
            The simplest case of indexing with  N integers returns an array scalar  representing the corresponding item. As in Python, all indices are zero-based: for the  𝑖-th index 𝑛𝑖 , the valid range is 0≤𝑛𝑖 <𝑑𝑖 , where 𝑑𝑖  is the  i-th element of the shape of the array. Negative indices are interpreted as counting from the end of the array ( i.e., if 𝑛𝑖 <0, it means 𝑛𝑖 +𝑑𝑖 ).
     
        All arrays generated by basic slicing are always views of the original array. 
        
            Note: NumPy slicing creates a view instead of a copy as in the case of builtin Python sequences such as string, tuple and list. Care must be taken when extracting a small portion from a large array which becomes useless after the extraction, because the small portion extracted contains a reference to the large original array whose memory will not be released until all arrays derived from it are garbage-collected. In such cases an explicit copy()is recommended. 
        The standard rules of sequence slicing apply to basic slicing on a per-dimension basis (including using a step index). Some useful concepts to remember include: 
        
The basic slice syntax is 𝑖:𝑗:𝑘where𝑖is the starting index,𝑗is the stopping index, and𝑘is the step (𝑘≠0). This selects themelements (in the corresponding dimension) with index values𝑖,𝑖+𝑘, …,𝑖+(𝑚-1)𝑘where 𝑚=𝑞+(𝑟≠0) and𝑞and𝑟are the quotient and remainder obtained by dividing𝑗−𝑖by𝑘:𝑗−𝑖=𝑞𝑘+𝑟, so that𝑖+(𝑚−1)𝑘<𝑗.Example >>> x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>x[1:7:2]
>>>array([1, 3, 5])
        Negative 𝑖and𝑗are interpreted as𝑛+𝑖and𝑛+𝑗where𝑛is the number of elements in the corresponding dimension. Negative𝑘makes stepping go towards smaller indices. 
Example >>> x[-2:10]
array([8, 9])
>>> x[-3:3:-1]
array([7, 6, 5, 4])
        Assume 𝑛is the number of elements in the dimension being sliced. Then, if𝑖is not given it defaults to 0 for𝑘>0and𝑛−1for𝑘<0. If𝑗is not given it defaults to𝑛for𝑘>0and−𝑛−1for𝑘<0. If𝑘is not given it defaults to 1. Note that::is the same as:and means select all indices along this axis. Example >>> x[5:]
array([5, 6, 7, 8, 9])
If the number of objects in the selection tuple is less than 𝑁, 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]]])Ellipsisexpands to the number of:objects needed for the selection tuple to index all dimensions. In most cases, this means that length of the expanded selection tuple isx.ndim. There may only be a single ellipsis present.
 Example >>> x[...,0]
array([[1, 2, 3],
       [4, 5, 6]])
Each newaxisobject in the selection tuple serves to expand the dimensions of the resulting selection by one unit-length dimension. 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+1exceptthe dimensionality of the returned object is reduced by 1. In particular, a selection tuple with thep-th element an integer (and all other entries:) returns the corresponding sub-array with dimensionN - 1. IfN = 1then the returned object is an array scalar. These objects are explained in Scalars.
                    
                        If the selection tuple has all entries :except thep-th entry which is a slice objecti:j:k, then the returned array has dimensionNformed by concatenating the sub-arrays returned by integer indexing of elementsi,i+k, …,i + (m - 1) k < j,
                    
                        Basic slicing with more than one non-:entry in the slicing tuple, acts like repeated application of slicing using a single non-:entry, where the non-:entries are successively taken (with all other non-:entries replaced by:). Thus,x[ind1,...,ind2,:]acts likex[ind1][...,ind2,:]under basic slicing. WarningThe above isnottrue for advanced indexing.You may use slicing to set values in the array, but (unlike lists) you can never grow the array. The size of the value to be set in x[obj] = valuemust be (broadcastable) to the same shape asx[obj]. Note
Remember that a slicing tuple can always be constructed as  obj and used in the  x[obj] notation. Slice objects can be used in the construction in place of the  [start:stop:step] notation. For example,  x[1:10:5,::-1] can also be implemented as  obj = (slice(1,10,5), slice(None,None,-1)); x[obj] . This can be useful for constructing generic code that works on arrays of arbitrary dimension.
 numpy.newaxis
The  newaxis object can be used in all slicing operations to create an axis of length one.  newaxis is an alias for ‘None’, and ‘None’ can be used in place of this with the same result.
 Advanced Indexing
                Advanced indexing is triggered when the selection object, obj, is a non-tuple sequence object, anndarray(of data type integer or bool), or a tuple with at least one sequence object or ndarray (of data type integer or bool). There are two types of advanced indexing: integer and Boolean. 
                Advanced indexing always returns a copyof the data (contrast with basic slicing that returns a view). Warning
                    The definition of advanced indexing means that x[(1,2,3),]is fundamentally different thanx[(1,2,3)]. The latter is equivalent tox[1,2,3]which will trigger basic selection while the former will trigger advanced indexing. Be sure to understand why this occurs. 
                    Also recognize that x[[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
                    Integer array indexing allows selection of arbitrary items in the array based on their N-dimensional index. Each integer array represents a number of indexes into that dimension. 
                    Purely integer array indexing
                        When the index consists of as many integer arrays as the array being indexed has dimensions, the indexing is straight forward, but different from slicing. 
                        Advanced indexes always are broadcast and iterated as one: 
                        
                            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 array shapes ind_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 the corresponding row, here  [0, 1, 0]. Using both together the task can 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 be used. The function  ix_ can help with this broadcasting. This is best understood with an example.
 Example
From a 4x3 array the corner elements should be selected using advanced indexing. Thus all elements for which the column is one of  [0, 2] and the row is one of  [0, 3] need to be selected. To use advanced indexing one needs to select all elements  explicitly. Using the method explained previously one could write:
 >>> x = np.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 as  rows[:, 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 function ix_: 
            
                
                    
                        x[np.ix_(rows, columns)]
array([[ 0,  2],
       [ 9, 11]])
 
                    Note that without the np.ix_call, only the diagonal elements would be selected, as was used in the previous example. This difference is the most important thing to remember about indexing with multiple advanced indexes. Combining advanced and basic indexing
                When there is at least one slice (:), ellipsis (...) ornewaxisin the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element 
                In the simplest case, there is only a singleadvanced index. A single advanced index can for example replace a slice and the result array will be the same, however, it is a copy and may have a different memory layout. A slice is preferable when it is possible.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 in terms of the result shape. There are two parts to the indexing operation, the subspace defined by the basic indexing (excluding integers) and the subspace from the advanced indexing part. Two cases of index combination need to be distinguished: 
                    
                        
                            The advanced indexes are separated by a slice, Ellipsisornewaxis. For examplex[arr1, :, arr2].
                        
                            The advanced indexes are all next to each other. For example x[..., arr1, arr2, :]butnotx[arr1, :, 1]since1is an advanced index in this regard. 
                    In the first case, the dimensions resulting from the advanced indexing operation come first in the result array, and the subspace dimensions after that. In the second case, the dimensions from the advanced indexing operations are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing). 
                    
                        Example 
                        Suppose x.shapeis (10,20,30) andindis a (2,3,4)-shaped indexingintparray, thenresult = x[...,ind,:]has shape (10,2,3,4,30) because the (20,)-shaped subspace has been replaced with a (2,3,4)-shaped broadcasted indexing subspace. If we leti, j, kloop over the (2,3,4)-shaped subspace thenresult[...,i,j,k,:] = x[...,ind[i,j,k],:]. This example produces the 
                        same result asx.take(ind, axis=-2). 
                    
                        Example 
                        Let x.shapebe (10,20,30,40,50) and supposeind_1andind_2can 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 there is no unambiguous place to drop in the indexing subspace, thus it is tacked-on to the beginning. It is always possible to use.transpose()to move the subspace anywhere desired. Note that this example cannot be replicated usingtake. 
            Boolean array indexing
                This advanced indexing occurs when obj is an array object of Boolean type, such as may be returned from comparison operators. A single boolean index array is practically identical to x[obj.nonzero()]where, as described above,obj.nonzero()returns a tuple (of lengthobj.ndim) of integer index arrays showing theTrueelements ofobj. However, it is faster whenobj.shape == x.shape. 
                If obj.ndim == x.ndim,x[obj]returns a 1-dimensional array filled with the elements ofxcorresponding to theTruevalues ofobj. The search order will be row-major, C-style. IfobjhasTruevalues at 
                entries that are outside of the bounds ofx, then an index error will be raised. Ifobjis smaller thanxit 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 which are 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
 
            
                
                    x
array([  1.,  19.,  18.,   3.])
 
            In general if an index includes a Boolean array, the result will be identical to inserting obj.nonzero()into the same position and 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 the boolean index has exactlyas many dimensions as it is supposed to work with. 
            
                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]])
 
            Combining multiple Boolean indexing arrays or a Boolean with an integer indexing array can best be understood with the obj.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 even number. At the same time columns 0 and 2 should be selected with an advanced integer index. Using the ix_function this can be done with: x = np.array([[ 0,  1,  2],
               [ 3,  4,  5],
               [ 6,  7,  8],
               [ 9, 10, 11]])
 rows = (x.sum(-1) % 2) == 0
 rows
array([False,  True, False,  True])
 columns = [0, 2]
 
            
                x[np.ix_(rows, columns)]
array([[ 3,  5],
       [ 9, 11]])
 
            Without the np.ix_call, only the diagonal elements would be selected. 
            Or without np.ix_(compare the integer array examples): rows = rows.nonzero()[0]
 
            
                
                    
                        
                            x[rows[:, np.newaxis], columns]
array([[ 3,  5],
       [ 9, 11]])
 
            Detailed notes
                These are some detailed notes, which are not of importance for day to day indexing (in no particular order): 
                
                    
                        The native NumPy indexing type is intpand may differ from the default integer array type.intpis the smallest data type sufficient to safely index any array; for advanced indexing it may be faster than other types.
                    
                        For advanced assignments, there is in general no guarantee for the iteration order. This means that if an element is set more than once, it is not possible to predict the final result.
                    
                        An empty (tuple) index is a full scalar index into a zero dimensional array. x[()]returns ascalarifxis zero dimensional and a view otherwise. On the other handx[...]always returns a view.
                    
                        If a zero dimensional array is present in the index andit is a full integer index the result will be ascalarand not a zero dimensional array. (Advanced indexing is not triggered.)
                    
                        When an ellipsis (...) is present but has no size (i.e. replaces zero:) the result will still always be an array. A view if no advanced index is present, otherwise a copy.
                    
                        the nonzeroequivalence for Boolean arrays does not hold for zero dimensional boolean arrays.
                    
                        When the result of an advanced indexing operation has no elements but an individual index is out of bounds, whether or not an IndexErroris raised is undefined (e.g.x[[], [123]]with123being out of bounds).
                    
                        When a castingerror occurs during assignment (for example updating a numerical array using a sequence of strings), the array being assigned to may end up in an unpredictable partially updated state. However, if any other error (such as an out of bounds index) occurs, the array will remain unchanged.
                    
                        The memory layout of an advanced indexing result is optimized for each indexing operation and no particular memory order can be assumed.
                    
                        When using a subclass (especially one which manipulates its shape), the default ndarray.__setitem__behaviour will call__getitem__forbasicindexing but not foradvancedindexing. For such a subclass it may be preferable to callndarray.__setitem__with abase classndarray view on the data. Thismustbe done if the subclasses__getitem__does not return views. Field Access
                If the ndarrayobject is a structured array the fields of the array can be accessed by indexing the array with strings, dictionary-like. 
                Indexing x['field-name']returns a new view to the array, which is of the same shape asx(except when the field is a sub-array) but of data typex.dtype['field-name']and contains only the part of the data in the specified field. Also record 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']]. As of NumPy 1.16 this returns a view containing only those fields. In older versions of numpy it returned a copy. See the user guide section on Structured arrays for more information on multifield indexing. 
                If the accessed field is a sub-array, the dimensions of the sub-array are appended to the shape of the result.x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))])
x['a'].shape
(2, 2)
 x['a'].dtype
dtype('int32')
x['b'].shape
(2, 2, 3, 3)
 
            
                
                    
                        x['b'].dtype
dtype('float64')
 
            Flat Iterator indexing
                x.flatreturns an iterator that will iterate over the entire array (in C-contiguous style with the last index varying the fastest). This iterator object can also be indexed using basic slicing or advanced indexing as long as the selection object is not a tuple. This should be clear from the fact thatx.flatis a 1-dimensional view. It can be used for integer indexing with 1-dimensional C-style-flat indices. The shape of any returned array is therefore the shape of the integer indexing object. Source and Reference
        https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing ©sideway
 
 ID: 220100017 Last Updated: 1/17/2022 Revision: 0 |  |