NumPy array slicing extracts portions of an array — rows, columns, or submatrices — using Python slice syntax inside the subscript operator. Slicing returns a view into the original array (not a copy), so modifications can affect the original.

For a 2D array (matrix-like), slicing applies independently to each dimension separated by commas inside the brackets.

Example array

Consider a 4×4 NumPy array:

import numpy as np
arr = np.array([
    [ 1,  2,  3,  4],
    [ 5,  6,  7,  8],
    [ 9, 10, 11, 12],
    [13, 14, 15, 16]
])

Selecting individual rows

arr[0]        # first row: [1, 2, 3, 4]
arr[2]        # third row: [9, 10, 11, 12]
arr[-1]       # last row:  [13, 14, 15, 16]

A single integer index selects one row, returning a 1D array.

Selecting row ranges

Slicing a 1D index returns multiple rows:

arr[0:2]      # first two rows: [[1, 2, 3, 4], [5, 6, 7, 8]]
arr[:2]       # equivalent (start defaults to 0)
arr[1:]       # all rows from index 1: [[5, 6, 7, 8], ...]
arr[::2]      # every other row: rows 0 and 2

Selecting columns

To select columns, you need to specify both dimensions. Use : for “all rows”:

arr[:, 0]      # first column: [1, 5, 9, 13]
arr[:, 2]      # third column: [3, 7, 11, 15]
arr[:, -1]     # last column: [4, 8, 12, 16]

Without the leading :, a single index would select a row, not a column.

Selecting column ranges

arr[:, 0:2]    # first two columns
arr[:, 1:]     # all columns from index 1
arr[:, ::2]    # every other column

Submatrix selection

Slicing both dimensions selects a submatrix:

arr[0:2, 1:3]
# Result:
# [[2, 3],
#  [6, 7]]

This selects rows 0–1 and columns 1–2 — a 2×2 submatrix.

The general form for a 2D submatrix:

arr[row_start:row_stop, col_start:col_stop]

For higher-dimensional arrays (3D, 4D, etc.), add more comma-separated slice expressions, one per dimension.

Step parameter

The slice syntax start:stop:step includes an optional step. For reversing or downsampling:

arr[::-1]              # rows in reverse order
arr[:, ::-1]           # columns in reverse order
arr[::2, ::2]          # every other row AND every other column

Views vs copies

Slicing returns a view — a pointer into the original array’s memory, not a new array. Modifying the slice modifies the original:

sub = arr[0:2, 0:2]
sub[0, 0] = 999
print(arr[0, 0])    # prints 999 — original was modified

To get an independent copy, explicitly call .copy():

sub = arr[0:2, 0:2].copy()
sub[0, 0] = 999
print(arr[0, 0])    # still 1

Views are memory-efficient (no data copied) but the aliasing behavior surprises people. Be deliberate.

When to use slicing

Slicing is the primary way to:

  • Extract regions of interest from images (matrix-style data).
  • Pull out specific channels (e.g., RGB) from multi-channel data.
  • Decompose matrices for block-wise computation.
  • Set up training/validation splits in machine-learning pipelines.

For more selective indexing using boolean conditions, see NumPy advanced indexing. For arithmetic on slices, see NumPy arithmetic and comparison operations.