Movatterモバイル変換


[0]ホーム

URL:


SciPy

Indexing

Array indexing refers to any use of the square brackets ([]) to indexarray values. There are many options to indexing, which give numpyindexing great power, but with power comes some complexity and thepotential for confusion. This section is just an overview of thevarious options and issues related to indexing. Aside from singleelement indexing, the details on most of these options are to befound in related sections.

Assignment vs referencing

Most of the following examples show the use of indexing whenreferencing data in an array. The examples work just as wellwhen assigning to an array. See the section at the end forspecific examples and explanations on how assignments work.

Single element indexing

Single element indexing for a 1-D array is what one expects. It workexactly like that for other standard Python sequences. It is 0-based,and accepts negative indices for indexing from the end of the array.

>>>x=np.arange(10)>>>x[2]2>>>x[-2]8

Unlike lists and tuples, numpy arrays support multidimensional indexingfor multidimensional arrays. That means that it is not necessary toseparate each dimension’s index into its own set of square brackets.

>>>x.shape=(2,5)# now x is 2-dimensional>>>x[1,3]8>>>x[1,-1]9

Note that if one indexes a multidimensional array with fewer indicesthan dimensions, one gets a subdimensional array. For example:

>>>x[0]array([0, 1, 2, 3, 4])

That is, each index specified selects the array corresponding to therest of the dimensions selected. In the above example, choosing 0means that the remaining dimension of length 5 is being left unspecified,and that what is returned is an array of that dimensionality and size.It must be noted that the returned array is not a copy of the original,but points to the same values in memory as does the original array.In this case, the 1-D array at the first position (0) is returned.So using a single index on the returned array, results in a singleelement being returned. That is:

>>>x[0][2]2

So note thatx[0,2]=x[0][2] though the second case is moreinefficient as a new temporary array is created after the first indexthat is subsequently indexed by 2.

Note to those used to IDL or Fortran memory order as it relates toindexing. NumPy uses C-order indexing. That means that the lastindex usually represents the most rapidly changing memory location,unlike Fortran or IDL, where the first index represents the mostrapidly changing location in memory. This difference represents agreat potential for confusion.

Other indexing options

It is possible to slice and stride arrays to extract arrays of thesame number of dimensions, but of different sizes than the original.The slicing and striding works exactly the same way it does for listsand tuples except that they can be applied to multiple dimensions aswell. A few examples illustrates best:

>>>x=np.arange(10)>>>x[2:5]array([2, 3, 4])>>>x[:-7]array([0, 1, 2])>>>x[1:7:2]array([1, 3, 5])>>>y=np.arange(35).reshape(5,7)>>>y[1:5:2,::3]array([[ 7, 10, 13],       [21, 24, 27]])

Note that slices of arrays do not copy the internal array data butalso produce new views of the original data.

It is possible to index arrays with other arrays for the purposes ofselecting lists of values out of arrays into new arrays. There aretwo different ways of accomplishing this. One uses one or more arraysof index values. The other involves giving a boolean array of the propershape to indicate the values to be selected. Index arrays are a verypowerful tool that allow one to avoid looping over individual elements inarrays and thus greatly improve performance.

It is possible to use special features to effectively increase thenumber of dimensions in an array through indexing so the resultingarray aquires the shape needed for use in an expression or with aspecific function.

Index arrays

NumPy arrays may be indexed with other arrays (or any other sequence-like object that can be converted to an array, such as lists, with theexception of tuples; see the end of this document for why this is). Theuse of index arrays ranges from simple, straightforward cases tocomplex, hard-to-understand cases. For all cases of index arrays, whatis returned is a copy of the original data, not a view as one gets forslices.

Index arrays must be of integer type. Each value in the array indicateswhich value in the array to use in place of the index. To illustrate:

>>>x=np.arange(10,1,-1)>>>xarray([10,  9,  8,  7,  6,  5,  4,  3,  2])>>>x[np.array([3,3,1,8])]array([7, 7, 9, 2])

The index array consisting of the values 3, 3, 1 and 8 correspondinglycreate an array of length 4 (same as the index array) where each indexis replaced by the value the index array has in the array being indexed.

Negative values are permitted and work as they do with single indicesor slices:

>>>x[np.array([3,3,-3,8])]array([7, 7, 4, 2])

It is an error to have index values out of bounds:

>>>x[np.array([3,3,20,8])]<type 'exceptions.IndexError'>: index 20 out of bounds 0<=index<9

Generally speaking, what is returned when index arrays are used isan array with the same shape as the index array, but with the typeand values of the array being indexed. As an example, we can use amultidimensional index array instead:

>>>x[np.array([[1,1],[2,3]])]array([[9, 9],       [8, 7]])

Indexing Multi-dimensional arrays

Things become more complex when multidimensional arrays are indexed,particularly with multidimensional index arrays. These tend to bemore unusual uses, but they are permitted, and they are useful for someproblems. We’ll start with the simplest multidimensional case (usingthe array y from the previous examples):

>>>y[np.array([0,2,4]),np.array([0,1,2])]array([ 0, 15, 30])

In this case, if the index arrays have a matching shape, and there isan index array for each dimension of the array being indexed, theresultant array has the same shape as the index arrays, and the valuescorrespond to the index set for each position in the index arrays. Inthis example, the first index value is 0 for both index arrays, andthus the first value of the resultant array is y[0,0]. The next valueis y[2,1], and the last is y[4,2].

If the index arrays do not have the same shape, there is an attempt tobroadcast them to the same shape. If they cannot be broadcast to thesame shape, an exception is raised:

>>>y[np.array([0,2,4]),np.array([0,1])]<type 'exceptions.ValueError'>: shape mismatch: objects cannot bebroadcast to a single shape

The broadcasting mechanism permits index arrays to be combined withscalars for other indices. The effect is that the scalar value is usedfor all the corresponding values of the index arrays:

>>>y[np.array([0,2,4]),1]array([ 1, 15, 29])

Jumping to the next level of complexity, it is possible to onlypartially index an array with index arrays. It takes a bit of thoughtto understand what happens in such cases. For example if we just useone index array with y:

>>>y[np.array([0,2,4])]array([[ 0,  1,  2,  3,  4,  5,  6],       [14, 15, 16, 17, 18, 19, 20],       [28, 29, 30, 31, 32, 33, 34]])

What results is the construction of a new array where each value ofthe index array selects one row from the array being indexed and theresultant array has the resulting shape (number of index elements,size of row).

An example of where this may be useful is for a color lookup tablewhere we want to map the values of an image into RGB triples fordisplay. The lookup table could have a shape (nlookup, 3). Indexingsuch an array with an image with shape (ny, nx) with dtype=np.uint8(or any integer type so long as values are with the bounds of thelookup table) will result in an array of shape (ny, nx, 3) where atriple of RGB values is associated with each pixel location.

In general, the shape of the resultant array will be the concatenationof the shape of the index array (or the shape that all the index arrayswere broadcast to) with the shape of any unused dimensions (those notindexed) in the array being indexed.

Boolean or “mask” index arrays

Boolean arrays used as indices are treated in a different mannerentirely than index arrays. Boolean arrays must be of the same shapeas the initial dimensions of the array being indexed. In themost straightforward case, the boolean array has the same shape:

>>>b=y>20>>>y[b]array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34])

Unlike in the case of integer index arrays, in the boolean case, theresult is a 1-D array containing all the elements in the indexed arraycorresponding to all the true elements in the boolean array. Theelements in the indexed array are always iterated and returned inrow-major (C-style) order. The result is also identical toy[np.nonzero(b)]. As with index arrays, what is returned is a copyof the data, not a view as one gets with slices.

The result will be multidimensional if y has more dimensions than b.For example:

>>>b[:,5]# use a 1-D boolean whose first dim agrees with the first dim of yarray([False, False, False,  True,  True])>>>y[b[:,5]]array([[21, 22, 23, 24, 25, 26, 27],       [28, 29, 30, 31, 32, 33, 34]])

Here the 4th and 5th rows are selected from the indexed array andcombined to make a 2-D array.

In general, when the boolean array has fewer dimensions than the arraybeing indexed, this is equivalent to y[b, …], which meansy is indexed by b followed by as many : as are needed to fillout the rank of y.Thus the shape of the result is one dimension containing the numberof True elements of the boolean array, followed by the remainingdimensions of the array being indexed.

For example, using a 2-D boolean array of shape (2,3)with four True elements to select rows from a 3-D array of shape(2,3,5) results in a 2-D result of shape (4,5):

>>>x=np.arange(30).reshape(2,3,5)>>>xarray([[[ 0,  1,  2,  3,  4],        [ 5,  6,  7,  8,  9],        [10, 11, 12, 13, 14]],       [[15, 16, 17, 18, 19],        [20, 21, 22, 23, 24],        [25, 26, 27, 28, 29]]])>>>b=np.array([[True,True,False],[False,True,True]])>>>x[b]array([[ 0,  1,  2,  3,  4],       [ 5,  6,  7,  8,  9],       [20, 21, 22, 23, 24],       [25, 26, 27, 28, 29]])

For further details, consult the numpy reference documentation on array indexing.

Combining index arrays with slices

Index arrays may be combined with slices. For example:

>>>y[np.array([0,2,4]),1:3]array([[ 1,  2],       [15, 16],       [29, 30]])

In effect, the slice is converted to an index arraynp.array([[1,2]]) (shape (1,2)) that is broadcast with the index arrayto produce a resultant array of shape (3,2).

Likewise, slicing can be combined with broadcasted boolean indices:

>>>y[b[:,5],1:3]array([[22, 23],       [29, 30]])

Structural indexing tools

To facilitate easy matching of array shapes with expressions and inassignments, the np.newaxis object can be used within array indicesto add new dimensions with a size of 1. For example:

>>>y.shape(5, 7)>>>y[:,np.newaxis,:].shape(5, 1, 7)

Note that there are no new elements in the array, just that thedimensionality is increased. This can be handy to combine twoarrays in a way that otherwise would require explicitly reshapingoperations. For example:

>>>x=np.arange(5)>>>x[:,np.newaxis]+x[np.newaxis,:]array([[0, 1, 2, 3, 4],       [1, 2, 3, 4, 5],       [2, 3, 4, 5, 6],       [3, 4, 5, 6, 7],       [4, 5, 6, 7, 8]])

The ellipsis syntax maybe used to indicate selecting in full anyremaining unspecified dimensions. For example:

>>>z=np.arange(81).reshape(3,3,3,3)>>>z[1,...,2]array([[29, 32, 35],       [38, 41, 44],       [47, 50, 53]])

This is equivalent to:

>>>z[1,:,:,2]array([[29, 32, 35],       [38, 41, 44],       [47, 50, 53]])

Assigning values to indexed arrays

As mentioned, one can select a subset of an array to assign to usinga single index, slices, and index and mask arrays. The value beingassigned to the indexed array must be shape consistent (the same shapeor broadcastable to the shape the index produces). For example, it ispermitted to assign a constant to a slice:

>>>x=np.arange(10)>>>x[2:7]=1

or an array of the right size:

>>>x[2:7]=np.arange(5)

Note that assignments may result in changes if assigninghigher types to lower types (like floats to ints) or evenexceptions (assigning complex to floats or ints):

>>>x[1]=1.2>>>x[1]1>>>x[1]=1.2j<type 'exceptions.TypeError'>: can't convert complex to long; uselong(abs(z))

Unlike some of the references (such as array and mask indices)assignments are always made to the original data in the array(indeed, nothing else would make sense!). Note though, that someactions may not work as one may naively expect. This particularexample is often surprising to people:

>>>x=np.arange(0,50,10)>>>xarray([ 0, 10, 20, 30, 40])>>>x[np.array([1,1,3,1])]+=1>>>xarray([ 0, 11, 20, 31, 40])

Where people expect that the 1st location will be incremented by 3.In fact, it will only be incremented by 1. The reason is becausea new array is extracted from the original (as a temporary) containingthe values at 1, 1, 3, 1, then the value 1 is added to the temporary,and then the temporary is assigned back to the original array. Thusthe value of the array at x[1]+1 is assigned to x[1] three times,rather than being incremented 3 times.

Dealing with variable numbers of indices within programs

The index syntax is very powerful but limiting when dealing witha variable number of indices. For example, if you want to writea function that can handle arguments with various numbers ofdimensions without having to write special case code for eachnumber of possible dimensions, how can that be done? If onesupplies to the index a tuple, the tuple will be interpretedas a list of indices. For example (using the previous definitionfor the array z):

>>>indices=(1,1,1,1)>>>z[indices]40

So one can use code to construct tuples of any number of indicesand then use these within an index.

Slices can be specified within programs by using the slice() functionin Python. For example:

>>>indices=(1,1,1,slice(0,2))# same as [1,1,1,0:2]>>>z[indices]array([39, 40])

Likewise, ellipsis can be specified by code by using the Ellipsisobject:

>>>indices=(1,Ellipsis,1)# same as [1,...,1]>>>z[indices]array([[28, 31, 34],       [37, 40, 43],       [46, 49, 52]])

For this reason it is possible to use the output from the np.nonzero()function directly as an index since it always returns a tuple of indexarrays.

Because the special treatment of tuples, they are not automaticallyconverted to an array as a list would be. As an example:

>>>z[[1,1,1,1]]# produces a large arrayarray([[[[27, 28, 29],         [30, 31, 32], ...>>>z[(1,1,1,1)]# returns a single value40

Table Of Contents

Previous topic

Importing data withgenfromtxt

Next topic

Broadcasting

Quick search

  • © Copyright 2008-2018, The SciPy community.
  • Last updated on Jul 24, 2018.
  • Created usingSphinx 1.6.6.

[8]ページ先頭

©2009-2025 Movatter.jp