Written and maintained by CASRAI Editorial Board
Published · Last updated
On this page
Researchers and analysts searching “index of NumPy” usually want to know how to pull values out of a NumPy array: by position, by slice, by a list of positions, or by a true/false mask. This guide covers all four, says which return a view and which return a copy, and flags the traps in the official NumPy documentation that most often change research results silently.
Short answer: NumPy indexes arrays with square brackets. Integers and slices (x[1:7:2]) are “basic” indexing and return views; integer arrays and boolean arrays are “advanced” indexing and return copies. Positions start at 0 and negative numbers count from the end. (Source: NumPy user guide, “Indexing on ndarrays”, read 2026-11-08.)
What indexing is used for in research
Analysis code constantly selects part of an array: the readings from one condition, the rows that survived a quality filter, or every non-missing value before computing a mean. NumPy’s indexing syntax does this without loops. This page concerns array indexing; it is not about the index() method of Python lists or tuples.
Numpy indexing, indexing in NumPy, NumPy index, index NumPy
These phrasings all refer to the same mechanism. The NumPy documentation names three kinds: basic indexing (integers and slices), advanced indexing (integer or boolean arrays), and field access for structured arrays.
Install or access
Install from the official NumPy installation page (numpy.org/install). With pip, create and activate a virtual environment, then install:
python -m venv my-env
source my-env/bin/activate # macOS/Linux
my-env\Scripts\activate # Windows
pip install numpy
With conda: conda create -n my-env, then conda activate my-env, then conda install numpy (defaults or conda-forge channel). Check the install with import numpy as np; print(np.__version__). If importing fails with a C-extension error, NumPy maintains a troubleshooting page at numpy.org/doc/stable/user/troubleshooting-importerror.html.
Step-by-step: selecting values from an array
1. Basic indexing and slicing
Use start:stop:step. The stop position is excluded.
import numpy as np
x = np.arange(10)
x[1:7:2] # array([1, 3, 5])
x[-2] # 8
x[-3:3:-1] # array([7, 6, 5, 4])
An ellipsis (...) stands for as many full slices as needed, and np.newaxis (an alias of None) adds an axis of length one. The documentation states: “All arrays generated by basic slicing are always views of the original array.” Changing a slice therefore changes the original array.
2. Indexing with an array of positions (advanced)
x = np.arange(10, 1, -1)
x[np.array([3, 3, -3, 8])] # array([7, 7, 4, 2])
y = np.arange(35).reshape(5, 7)
y[np.array([0, 2, 4]), np.array([0, 1, 2])] # array([ 0, 15, 30])
With one index array per axis, NumPy pairs them element by element (here the positions (0,0), (2,1) and (4,2)). Positions may repeat. The documentation states: “Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).”
3. Selecting a block of rows and columns with np.ix_
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
rows = [0, 3]
columns = [0, 2]
x[np.ix_(rows, columns)]
# array([[ 0, 2],
# [ 9, 11]])
x[rows, columns] # array([ 0, 11])
The same two lists give different results. x[rows, columns] pairs them and returns two values; np.ix_ builds the cross-product and returns the 2×2 block. The documentation calls this “the most important thing to remember about indexing with multiple advanced indices.”
4. Boolean masks: filtering by a condition
x = np.array([1., np.nan, 3.])
x[~np.isnan(x)] # array([1., 3.])
x = np.array([1., -1., -2., 3])
x[x < 0] += 20 # x is now array([ 1., 19., 18., 3.])
This is the standard way to drop missing readings before computing a statistic: the mask ~np.isnan(x) is true where a value is present. A boolean mask on a multi-dimensional array returns a one-dimensional result in row-major order. The documentation notes that a boolean index obj behaves like x[obj.nonzero()]. For finding positions with a condition rather than values, see NumPy where.
5. Mixing slices and index arrays
y[np.array([0, 2, 4]), 1:3] equals y[:, 1:3][np.array([0, 2, 4]), :]: the slice is applied to one axis and the index array to the other. When advanced indices are separated by a slice or np.newaxis, their dimensions go first in the result; when adjacent, they stay in place. For an array x of shape (10, 20, 30, 40, 50), the documentation’s example x[:, ind_1, :, ind_2] yields shape (2, 3, 4, 10, 30, 50).
6. numpy.take
numpy.take(a, indices, axis=None, out=None, mode='raise') picks elements along one axis; with axis=None the array is flattened first. np.take([4, 3, 5, 7, 6, 8], [0, 1, 4]) returns array([4, 3, 6]). The mode argument sets out-of-range behaviour: 'raise' (error), 'wrap', or 'clip' (which disables negative indexing). np.take(arr, indices, axis=3) is equivalent to arr[:, :, :, indices, ...].
Output and how to read it: view or copy, and out-of-range behaviour
| Method | Selects by | Result | Out-of-range position |
|---|---|---|---|
| Basic indexing / slices | Integers, start:stop:step |
View of the original | IndexError for a single integer |
| Integer-array indexing | Array of positions | Copy | IndexError |
| Boolean mask | True/false array | Copy (1-D result) | Selects by condition, not position |
numpy.take |
Positions along one axis | New array | Set by mode: raise, wrap or clip |
Source: NumPy user guide, “Indexing on ndarrays”, and the numpy.take reference page, both read 2026-11-08. The view/copy distinction matters for research code: assigning into a slice edits your source data, while assigning into the result of advanced indexing does not. The documentation also advises an explicit copy() when a small slice would otherwise keep a large array alive in memory. x[...] always returns a view.
Three traps that change results without an error
- Paired versus cross-product indices.
x[rows, columns]andx[np.ix_(rows, columns)]return different things (step 3). - Repeated indices and in-place addition.
x[np.array([1, 1, 3, 1])] += 1incrementsx[1]only once, not three times, per the documentation. - Silent truncation on assignment. Assigning a float into an integer array truncates it (
x[1] = 1.2stores 1). Assigning a complex number raisesTypeError(can’t convert complex to int). Check the dtype before writing computed values back.
Troubleshooting
IndexError: index 3 is out of bounds for axis 0 with size 3means a position exceeds the axis length. Valid positions run from -size to size-1.IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)means the index arrays have incompatible lengths. Make them equal length, or usenp.ix_if you want a cross-product.- Unexpected changes to original data after editing a “subset” usually mean the subset was a view. Call
.copy()first. - Related array operations: NumPy delete, ravel in NumPy, NumPy arrays and reversing a vector in NumPy. If you are coming from MATLAB, see MATLAB indexing for the matching concepts on that side.
FAQ
What does “index of NumPy” mean?
It normally means how to index a NumPy array: select elements by position, slice, integer array or boolean mask using square brackets. It is distinct from the list.index() method in core Python.
Do NumPy arrays start at 0 or 1?
0. x[0] is the first element and x[-1] the last. The examples above, such as x[-2] returning 8 on np.arange(10), follow this.
Does indexing return a view or a copy?
Basic slicing returns a view; advanced indexing (integer or boolean arrays) returns a copy, per the NumPy user guide.
How do I remove NaN values from an array?
x[~np.isnan(x)] keeps only the values that are not NaN.
Sources
- NumPy user guide, “Indexing on ndarrays”: numpy.org/doc/stable/user/basics.indexing.html (read 2026-11-08).
- NumPy reference,
numpy.take: numpy.org/doc/stable/reference/generated/numpy.take.html (read 2026-11-08). - NumPy installation instructions: numpy.org/install (read 2026-11-08).







