0

I have a numpy array with shape (M, N, N) - it's effectively a bunch (M) of (N,N) covariance matrices. I want to be able to extract submatrices out of this with shape (M, P, P). But I'm trying to access non-contiguous indices. Here's an example:

import numpy as np

# Display all the columns
np.set_printoptions(threshold=False, edgeitems=50, linewidth=200)

# Create a 6 x 6 matrix.
x = np.arange(36).reshape(6,6)

# Now make multiple copies to practice with.
y = np.array([x, x])

print(f"{y.shape=}\n")

print(f"{y=}\n")

# We want to extract the submatrices containting the first 2 indices
# and the last 2 indices. There are an "unknown" number of intermediate
# indices - in this example 2. Thus I'm using negative indices to get the
# last two indicies.

# Extraction using advanced indexing
s = np.array([[0, 1] + [-2, -1]])

subset = y[:, s.T, s]
print(f"{subset=}\n")

# Now try it with numpy slices. This approach doesn't work
first_slice = np.s_[0:2]
second_slice = np.s_[-2:]
combined_slice = np.r_[first_slice, second_slice]

subset = y[:, combined_slice, combined_slice]
print(subset)

That produces the following output:

y.shape=(2, 6, 6)

y=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, 32, 33, 34, 35]],

       [[ 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, 32, 33, 34, 35]]])

subset=array([[[ 0,  1,  4,  5],
        [ 6,  7, 10, 11],
        [24, 25, 28, 29],
        [30, 31, 34, 35]],

       [[ 0,  1,  4,  5],
        [ 6,  7, 10, 11],
        [24, 25, 28, 29],
        [30, 31, 34, 35]]])

[[0 7]
 [0 7]]

Using array based indexing works, but it seems like there should be a way to do this with slice objects too. Any tips would be appreciated. Thanks!

3
  • 3
    You can't make, or use, discontinuous slices. A slice is, by definition slice(start, stop, step), It can't be 'select 2, skip n, select 2'. And look at your combined_slices. It is just [0,1]. r_ expands slice notation into arange calls; it does not 'combine' slices as you seem to imagine. In general, complicated patterns that can't be expressed as slices have to be expanded into advanced indexing. Commented May 16, 2024 at 16:52
  • 1
    np.r_[0:2] expands to [0,1]. np.r_[-2:] expands to []. np.r_ doesn't know anything about the shape of y, so -2 from the end doesn't make any sense. np.r_[0:2, 4:6] produces [0,1,4,5], the same advanced indexing array as s. Commented May 16, 2024 at 17:01
  • @hpaulj I agree with your assessment. Thanks for taking the time to double-check me. Commented May 16, 2024 at 21:04

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.