Fancy index
Fancy indexing is a NumPy term, which refers to the use of integer arrays for indexing. Suppose we have an 8 × 4 array:
In [117]: arr = np.empty((8, 4)) In [118]: for i in range(8): .....: arr[i] = i In [119]: arr Out[119]: array([[ 0., 0., 0., 0.], [ 1., 1., 1., 1.], [ 2., 2., 2., 2.], [ 3., 3., 3., 3.], [ 4., 4., 4., 4.], [ 5., 5., 5., 5.], [ 6., 6., 6., 6.], [ 7., 7., 7., 7.]])
To select a subset of rows in a specific order, simply pass in a list of integers or ndarray s for the specified order:
In [120]: arr[[4, 3, 0, 6]] Out[120]: array([[ 4., 4., 4., 4.], [ 3., 3., 3., 3.], [ 0., 0., 0., 0.], [ 6., 6., 6., 6.]])
This code really meets our requirements! Using a negative index will pick rows from the end:
In [121]: arr[[-3, -5, -7]] Out[121]: array([[ 5., 5., 5., 5.], [ 3., 3., 3., 3.], [ 1., 1., 1., 1.]])
Passing in more than one index array at a time is a little special. It returns a one-dimensional array in which the elements correspond to the index tuples:
In [122]: arr = np.arange(32).reshape((8, 4)) In [123]: arr Out[123]: array([[ 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, 30, 31]]) In [124]: arr[[1, 5, 7, 2], [0, 3, 1, 2]] Out[124]: array([ 4, 23, 29, 10])
The reshape method is described in detail in Appendix A.
Finally, elements (1,0), (5,3), (7,1) and (2,2) were selected. No matter how many dimensions an array is, a fancy index is always one-dimensional.
The behavior of this fancy index may be different from what some users expect (including me). The row column subset of the selection matrix should be in the form of a rectangular region. Here is a way to get this result:
In [125]: arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]] Out[125]: array([[ 4, 7, 5, 6], [20, 23, 21, 22], [28, 31, 29, 30], [ 8, 11, 9, 10]])
Remember, unlike slicing, a fancy index always copies data into a new array.