Skip to content

Python NumPy: How to Extract a Submatrix from a 2D Array

Learn how to extract submatrices from 2D NumPy arrays using numpy.ix_() for arbitrary row/column selection and standard slicing for contiguous blocks.

Extracting a specific portion, or submatrix, from a larger 2D NumPy array is a fundamental operation in data manipulation and scientific computing. Whether you need to select specific rows and columns based on their indices, or pick out a contiguous block of data, NumPy offers powerful and efficient indexing mechanisms.

This guide will comprehensively demonstrate two primary methods for extracting submatrices: the versatile numpy.ix_() function for constructing indexers from sequences of row and column indices, and standard NumPy array slicing for selecting contiguous or regularly stepped portions of the array. You'll learn how to apply both techniques to precisely select the submatrix you need.

Understanding Submatrix Extraction

A submatrix is essentially a smaller 2D array derived from a larger 2D array by selecting a specific set of its rows and columns. The goal is to isolate a rectangular portion of the original array.

Let's define a sample 2D NumPy array for our examples:

import numpy as np

main_array = np.array([
    [10, 11, 12, 13, 14],  # Row 0
    [20, 21, 22, 23, 24],  # Row 1
    [30, 31, 32, 33, 34],  # Row 2
    [40, 41, 42, 43, 44],  # Row 3
    [50, 51, 52, 53, 54]   # Row 4
])
print("Original 2D NumPy Array (main_array):")
print(main_array)

Output:

Original 2D NumPy Array (main_array):
[[10 11 12 13 14]
 [20 21 22 23 24]
 [30 31 32 33 34]
 [40 41 42 43 44]
 [50 51 52 53 54]]

Method 1: Using numpy.ix_() for Arbitrary Row and Column Selection

The numpy.ix_() function is particularly useful when you want to construct a submatrix from specific, potentially non-contiguous, rows and columns. You provide sequences of row indices and column indices, and np.ix_() creates an open mesh that can be used for indexing.

How numpy.ix_() Works

np.ix_(rows_list, cols_list) takes lists (or arrays) of row indices and column indices. It returns a tuple of arrays that, when used to index the original array, effectively selects elements at the intersection of the specified rows and columns.

import numpy as np

main_array = np.array([
    [10, 11, 12, 13, 14],  # Row 0
    [20, 21, 22, 23, 24],  # Row 1
    [30, 31, 32, 33, 34],  # Row 2
    [40, 41, 42, 43, 44],  # Row 3
    [50, 51, 52, 53, 54]   # Row 4
])

row_indices = [0, 3]
col_indices = [1, 4]

index_constructor = np.ix_(row_indices, col_indices)
print(f"Output of np.ix_({row_indices}, {col_indices}):")
print(index_constructor)

Output:

Output of np.ix_([0, 3], [1, 4]):
(array([[0],
       [3]]), array([[1, 4]]))

Extracting a Submatrix with Specific Row and Column Indices

Using the index_constructor from np.ix_() to index main_array:

import numpy as np

main_array = np.array([
    [10, 11, 12, 13, 14],  # Row 0
    [20, 21, 22, 23, 24],  # Row 1
    [30, 31, 32, 33, 34],  # Row 2
    [40, 41, 42, 43, 44],  # Row 3
    [50, 51, 52, 53, 54]   # Row 4
])
row_indices = [0, 3]
col_indices = [1, 4]
index_constructor = np.ix_(row_indices, col_indices)


submatrix_ix = main_array[index_constructor]

print("Submatrix using np.ix_([0, 3], [1, 4]):")
print(submatrix_ix)

Output:

Submatrix using np.ix_([0, 3], [1, 4]):
[[11 14]
 [41 44]]

This submatrix consists of elements from:

  • Row 0, Column 1 (11) and Row 0, Column 4 (14)
  • Row 3, Column 1 (41) and Row 3, Column 4 (44)

More Examples of numpy.ix_()

  • Extract elements from rows 1 and 4, and columns 0 and 2:

    import numpy as np
    
    main_array = np.array([
        [10, 11, 12, 13, 14],  # Row 0
        [20, 21, 22, 23, 24],  # Row 1
        [30, 31, 32, 33, 34],  # Row 2
        [40, 41, 42, 43, 44],  # Row 3
        [50, 51, 52, 53, 54]   # Row 4
    ])
    
    submatrix_ex2 = main_array[np.ix_([1, 4], [0, 2])]
    print("Submatrix from rows [1, 4] and columns [0, 2]:")
    print(submatrix_ex2)

    Output:

    Submatrix from rows [1, 4] and columns [0, 2]:
    [[20 22]
     [50 52]]
  • Extract a "checkerboard" pattern - rows 0, 2, 4 and columns 0, 2, 4:

    import numpy as np
    
    main_array = np.array([
        [10, 11, 12, 13, 14],  # Row 0
        [20, 21, 22, 23, 24],  # Row 1
        [30, 31, 32, 33, 34],  # Row 2
        [40, 41, 42, 43, 44],  # Row 3
        [50, 51, 52, 53, 54]   # Row 4
    ])
    
    submatrix_ex3 = main_array[np.ix_([0, 2, 4], [0, 2, 4])]
    print("Submatrix from rows [0, 2, 4] and columns [0, 2, 4]:")
    print(submatrix_ex3)

    Output:

    Submatrix from rows [0, 2, 4] and columns [0, 2, 4]:
    [[10 12 14]
     [30 32 34]
     [50 52 54]]

Method 2: Using Standard NumPy Array Slicing

Standard NumPy slicing is excellent for extracting contiguous blocks of data or selecting elements with a regular step. The syntax is array[row_slice, col_slice], where each slice can be start:stop:step.

Basic Slicing for Contiguous Submatrices

To select a block of rows and columns. Remember that the stop index is exclusive.

import numpy as np

main_array = np.array([
    [10, 11, 12, 13, 14],  # Row 0
    [20, 21, 22, 23, 24],  # Row 1
    [30, 31, 32, 33, 34],  # Row 2
    [40, 41, 42, 43, 44],  # Row 3
    [50, 51, 52, 53, 54]   # Row 4
])

submatrix_slice1 = main_array[0:3, 1:4] # Rows 0,1,2 and Columns 1,2,3

print("Submatrix using slice [0:3, 1:4]:")
print(submatrix_slice1)
print()

submatrix_slice2 = main_array[:2, :3] # Omitting start implies 0
print("Submatrix from first 2 rows, first 3 columns [:2, :3]:")
print(submatrix_slice2)

Output:

Submatrix using slice [0:3, 1:4]:
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Submatrix from first 2 rows, first 3 columns [:2, :3]:
[[10 11 12]
 [20 21 22]]

Slicing with Steps for Non-Contiguous Regular Selections

The step component of a slice allows you to pick elements at regular intervals.

import numpy as np

main_array = np.array([
    [10, 11, 12, 13, 14],  # Row 0
    [20, 21, 22, 23, 24],  # Row 1
    [30, 31, 32, 33, 34],  # Row 2
    [40, 41, 42, 43, 44],  # Row 3
    [50, 51, 52, 53, 54]   # Row 4
])

submatrix_stepped_slice = main_array[0::2, 0::2]

print("Submatrix using stepped slice [::2, ::2]:")
print(submatrix_stepped_slice)
print()

arr_4x4 = np.arange(1, 17).reshape(4, 4)
print("Original 4x4 array:")
print(arr_4x4)
print()

sub_4x4 = arr_4x4[0:4:3, 0:4:3] # Rows 0, 3. Columns 0, 3.
print("Submatrix from 4x4 array [0:4:3, 0:4:3]:")
print(sub_4x4)

Output:

Submatrix using stepped slice [::2, ::2]:
[[10 12 14]
 [30 32 34]
 [50 52 54]]

Original 4x4 array:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

Submatrix from 4x4 array [0:4:3, 0:4:3]:
[[ 1  4]
 [13 16]]

Choosing Between np.ix_() and Standard Slicing

  • Use numpy.ix_() when:

    • You need to select rows and columns based on arbitrary, potentially non-sequential lists of indices.
    • You want to form a submatrix from specific "chosen" rows and columns.
    • Example: Rows [0, 3, 4] and Columns [1, 5, 6] from a larger matrix.
  • Use Standard Slicing (array[start:stop:step, start:stop:step]) when:

    • You are selecting a contiguous block of rows and columns.
    • You are selecting rows/columns with a regular step (e.g., every other row).
    • It's generally more concise for these specific patterns.

If you try to use a list of indices directly with standard slicing for both dimensions like arr[[0,3], [1,3]], NumPy performs "advanced indexing" which pairs up the indices, returning [arr[0,1], arr[3,3]] (a 1D array), not the 2x2 submatrix that np.ix_ would give. This is a key difference.

Conclusion

Extracting submatrices is a core NumPy skill.

  • For selecting elements based on specific lists of row and column indices to form a rectangular submatrix, numpy.ix_() is the appropriate tool (e.g., array[np.ix_([row_idx_list], [col_idx_list])]).
  • For selecting contiguous blocks or regularly stepped elements, standard NumPy slicing (array[row_slice, col_slice]) is efficient and direct.

Understanding these two powerful indexing methods allows you to precisely select and manipulate any desired portion of your 2D NumPy arrays.

Navigation