Indexing and Slicing NumPy Arrays

Sub arrays are created using NumPy slice notation which is a powerful data manipulation technique.
Andrew Wood  •   10 July 2022
Andrew Wood  •   Last Updated: 10 July 2022
Sub arrays are created using NumPy slice notation which is a powerful data manipulation technique.

This NumPy tutorial focuses on the indexing and slicing of NumPy arrays.

It is the second post in a series on NumPy and so if you are new to NumPy then perhaps go and check out our Introduction to NumPy before continuing with this tutorial.

Basics of Array Indexing

Size and Shape

The size and shape of arrays was covered in more detail in our first NumPy post, but we'll quickly revise it here as it is central to understanding how to create sub-arrays through slicing.

All NumPy arrays consist of a number of dimensions or axes. A 1D array has one axis, a 2D array has two, and so so. Axes are indexed to zero so that the first axis is called by axis=0.

To extract the number of axes from a NumPy array you can call .ndim on that array.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])
>>> print(arr.ndim)
2

The shape of an array refers to the lengths of the corresponding array dimensions. In the case of a 2D array this would refer to the number of rows and columns in the array. The shape is returned by calling .shape on the array which returns a tuple with the lengths of each dimension in the order of the axes. 

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2]])
>>> print(arr.shape)
(3,5) # three rows and five columns

Referring to Specific Elements

Refer to the 3 x 4 matrix printed below. The array axes are shown, as are the indices.

Example numpy array

To refer to a specific element, pass a tuple to the array with the indices listed in the order of the axes. Remember that axes are index based to zero. 

>>> arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> print(arr[(0,1)])
2
>>> print(arr[(1,2)] = 6
6

Slicing NumPy Arrays

List Type Slicing

Slicing of NumPy arrays is accomplished in much the same way is you would slice a Python list. A more detailed post on python list slicing is available here if you are looking for a refresher.

Slicing syntax is written [start:stop:step].

  • If start is omitted then slicing starts from the first item (index 0).
  • If stop is omitted then slicing will be considered from start to the end of the array.
  • If step is omitted then the stepping interval is considered to be 1.

We'll use the 4 x 5 matrix (array) given below to illustrate array slicing concepts. We have also created a simple function arrprint that will print out the array, its size, and its shape to illustrate the slicing functionality.

arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])

def arrprint(arr):
    return f"The array is {arr}, it has {arr.ndim} dimension(s) and shape: {arr.shape}"

To extract the first row:

>>> row1 = arr[0]
>>> print(arrprint(row1))
"The array is [3 4 5 6 4], it has 1 dimension(s) and shape: (5,)"

To extract the first two rows:

>>> tworows = arr[:2,:]
>>> print(arrprint(tworows))
"The array is [[3 4 5 6 4]
 [2 4 3 1 3]], it has 2 dimension(s) and shape: (2, 5)"

Extract the first two items in every row:

>>> arr2 = arr[:,0:2]
>>> print(arrprint(arr2))
"The array is [[3 4]
 [2 4]
 [7 6]
 [3 4]], it has 2 dimension(s) and shape: (4, 2)"

Slicing Returns a View

Slicing a NumPy array returns a shallow copy or a view of the original array. What this means is that while the size and shape of the sliced array will be different from the original, the values of the slice are stored in the same piece of memory as the original. This means that any changes made to the values in the slice will reference back to the original array.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])
>>> arr2 = arr[:,0:2]
>>> print(arr2)
[[3 4]
 [2 4]
 [7 6]
 [3 4]]

# now modify a value in arr2
>>> arr2[0,1] = 999 
>>> print(arr2)
[[  3 999]
 [  2   4]
 [  7   6]
 [  3   4]]

# print the original array
>>> print(arr)
[[  3 999   5   6   4]
 [  2   4   3   1   3]
 [  7   6   5   2   2]
 [  3   4   3   2   2]]

You can avoid this referencing back to the original array by appending the copy method to the end of the slice. This will make a copy of the sliced array and break its reference to the original array.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])
>>> arr2 = arr[:,0:2].copy() # make a deep copy of the array
>>> arr2[0,1] = 999 # modify arr2
>>> print(arr2)
[[  3 999]
 [  2   4]
 [  7   6]
 [  3   4]]

# now print the original array
>>> print(arr)
[[3 4 5 6 4]
 [2 4 3 1 3]
 [7 6 5 2 2]
 [3 4 3 2 2]]

Conditional Slicing

You can add conditional statements to your slicing if you need to extract elements that meet specific criteria from an array. The result is a flattened array of elements that meet the conditional criteria.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])

# flatten an array based on a criteria
>>> arr_five = arr[arr<5]
>>> print(arr_five)
[3 4 4 2 4 3 1 3 2 2 3 4 3 2 2]

# extract all odd numbers from the array
>>> arr_odd = arr[arr%2!=0]
>>> print(arr_odd)
[3 5 3 1 3 7 5 3 3]

You can also use conditionals to create an array of booleans corresponding to the array that the conditional is tested on. Pass the boolean array into the original array to return the resulting flattened array. Note the rounded brackets required to return a boolean array.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])
# create an array of booleans based on a particular criteria
>>> barr = (arr<=3)
>>> print(barr)
[[ True False False False False]
 [ True False  True  True  True]
 [False False False  True  True]
 [ True False  True  True  True]]
>>> print(barr.shape)
(4,5)

# now return the resulting flattened array
>>> barr_result = arr[barr]
>>> print(barr_result)
[3 2 3 1 3 2 2 3 3 2 2]

Working with Logical Operators

It is also possible to work with the logical operators AND and OR within your conditionals.

  • AND is written as & in the conditional.
  • OR is written as | in the conditional.

Let's run through a few examples to show these logical operators in action.

>>> arr = np.array([[3,4,5,6,4],[2,4,3,1,3],[7,6,5,2,2],[3,4,3,2,2]])

# select elements that satisfy multiple conditions
>>> carr = arr[(arr > 3) & (arr < 7)]
>>> print(carr)
[4 5 6 4 4 6 5 4]

>>> another = np.array([[1,1,2],[5,6,7],[2,2,2]])
>>> print(another[(another ==1)|(another ==5)])
[1 1 5]

You can create an array of booleans that satisfies multiple conditions in the same way as we showed for a single conditional, and use this to extract the filtered final result.

>>> aa = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> sixer = (aa > 6) | (aa == 6)
>>> print(sixer)
[[False False False False]
 [False  True  True  True]
 [ True  True  True  True]]

>>> ab = aa[sixer]
>>> print(ab)
[ 6  7  8  9 10 11 12]

Wrapping Up

We've come to the end of this tutorial on slicing methods on NumPy arrays. Slicing is a powerful technique that forms a part of the backbone of the NumPy package. In this tutorial we covered the following concepts:

  • Discussed array indexing and indexing of multidimensional arrays.
  • We looked at slicing of arrays and how the method is very similar to slicing Python lists.
  • We highlighted that slicing an array returns a view or shallow copy of the original array, which means that any changes made to values in the slice will be present in the original array also.
  • We added conditional statements to our slicing techniques and finished off by showing that you can slice based on multiple conditions using the AND (&) and OR (|) logical operators.

Thanks for reading! Now a shameless plug: if you liked what you read and it helped you better understand NumPy array slicing then please share this content to help us to grow this knowledge hub. Doing so will allow us to create even more high quality content and to keep it free.

Share this
Comments
Canard Analytics Founder. Python development, data nerd, aerospace engineering and general aviation.
Profile picture of andreww
Share Article

Looking for a partner on your next project?

Contact Us