Give np.ix_ a try:

Y[np.ix_([0,3],[0,3])]

This returns your desired result:

In [25]: Y = np.arange(16).reshape(4,4)
In [26]: Y[np.ix_([0,3],[0,3])]
Out[26]:
array([[ 0,  3],
       [12, 15]])
Answer from JoshAdel on Stack Overflow
🌐
IncludeHelp
includehelp.com › python › numpy-extract-submatrix.aspx
Python - NumPy: Extract Submatrix
January 23, 2023 - To extract a submatrix, we will use numpy.ix_() method.
Discussions

How to go over submatrices of a matrix - and fast?
First, I suggest a slight change of representation. Instead of a MxN matrix of tuples, you can have a 2xMxN matrix of integers. This is beneficial as you can then take the second index of the first dimension, and not have to deal with tuple indexing. If you already have your matrix of tuples you can convert it trivially: >>> a = [[( 1, 2), (1, 1), (0, 3), (4, 0)], >>> [ (10, 10), (5, 7), (1, 3), (9, 2)], >>> [ ( 0, 0), (1, 9), (0, 0), (1, 1)]] >>> a = np.moveaxis(np.array(a), -1, 0) # 2x3x4 matrix >>> a[1] [[ 2 1 3 0] [10 7 3 2] [ 0 9 0 1]] Now the problem is reduced to finding the "largest-sum PxQ submatrix smaller than B" of a[1]. So, how do we solve it optimally? No clue, but I came up with a simple method using a 2D cumulative sum, that I believe should be O(NxM) (correct me if I'm mistaken). [Complete runnable example] More on reddit.com
🌐 r/learnpython
7
2
April 7, 2022
python - Using numpy to Obtain Submatrix - Stack Overflow
I'm trying to do the following with numpy (python newbie here) Create a zeroed matrix of the rigth dimensions num_rows = 80 num_cols = 23 A = numpy.zeros(shape=(num_rows, num_cols)) Operate on the More on stackoverflow.com
🌐 stackoverflow.com
python - Numpy submatrix operations - Stack Overflow
I'm looking for an efficient way to perform submatrix operations over a larger matrix without resorting to for loops. I'm currently doing the operation (for a 3x3 window): newMatrix = numpy.zeros([numRows, numCols]) for i in range(1, numRows-1): for j in range(1, numCols-1): sub = matrix[i-1:i+2, ... More on stackoverflow.com
🌐 stackoverflow.com
a) Submatrix Extraction with NumPy Write a Python function extract_submatrix (matrix, rows_to_remove, cols_to_remove). This function takes the following parameters: - matrix: A 2D NumPy array (matrix) of shape (M, N) ( M,N>1). - rows_to_remove: A list of row indices to be removed from the original matrix. - cols_to_remove: A list of column indices to be
Answer to a) Submatrix Extraction with NumPy Write a Python More on chegg.com
🌐 chegg.com
1
November 22, 2023
🌐
Reddit
reddit.com › r/learnpython › how to go over submatrices of a matrix - and fast?
r/learnpython on Reddit: How to go over submatrices of a matrix - and fast?
April 7, 2022 -

Hi,

I have an MxN matrix (list of lists), where each element is a tuple of 2 ints.

Given a rectangle size PxQ, where P<=M, Q<=N), I need to find the submatrix inside the MxN matrix which, when calculating the sum of the second element of each tuple inside the rectangle, returns the highest result which is not larger than a number B. Each submatrix is defined by its upper-left corner.

For example, the MxN matrix can be:

[ [(1, 2), (1, 1), (0, 3), (4, 0)],

[(10, 10), (5, 7), (1, 3), (9, 2)],

[(0, 0), (1, 9), (0, 0), (1, 1)] ]

and the rectangle size can be 2x3, so there are 4 submatrices to go over:

[(1, 2), (1, 1), (0, 3)

(10, 10), (5, 7), (1, 3)]

[(1, 1), (0, 3), (4, 0)

(5, 7), (1, 3), (9, 2)]

[(10, 10), (5, 7), (1, 3)

(0, 0), (1, 9), (0, 0)]

[(5, 7), (1, 3), (9, 2)

(1, 9), (0, 0), (1, 1)]

If B=27, the correct submatrix, in this case, is the second one, since it has the highest sum of 2nd elements, which is 2+1+3+10+7+3=26, which is smaller than B. The third submatrix yields a larger sum (29) but 29 > 27 so it is not the right answer.

I'm looking for an efficient way to go over the submatrices and determine if the sum of the 2nd elements is the largest. Is there a faster way than using for loops?

Top answer
1 of 5
5
First, I suggest a slight change of representation. Instead of a MxN matrix of tuples, you can have a 2xMxN matrix of integers. This is beneficial as you can then take the second index of the first dimension, and not have to deal with tuple indexing. If you already have your matrix of tuples you can convert it trivially: >>> a = [[( 1, 2), (1, 1), (0, 3), (4, 0)], >>> [ (10, 10), (5, 7), (1, 3), (9, 2)], >>> [ ( 0, 0), (1, 9), (0, 0), (1, 1)]] >>> a = np.moveaxis(np.array(a), -1, 0) # 2x3x4 matrix >>> a[1] [[ 2 1 3 0] [10 7 3 2] [ 0 9 0 1]] Now the problem is reduced to finding the "largest-sum PxQ submatrix smaller than B" of a[1]. So, how do we solve it optimally? No clue, but I came up with a simple method using a 2D cumulative sum, that I believe should be O(NxM) (correct me if I'm mistaken). [Complete runnable example]
2 of 5
3
So if I understand your problem correctly, you have your MxN matrix. Your challenge is to find a subgrid (PxQ) such that the sum of all second values is as close to (but not exceeding) the value B. With regards to matrix calculations in Python, if you want speed, you want NumPy. It gives you fixed-size arrays with certain functionality implemented efficiently behind the scenes (e.g. summation of values - do you see how this could be useful?). It also allows you to perform indexing in multiple dimensions. See below for an example >>> import numpy as np >>> matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> print(matrix) array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> array[:2, :2] array([[1, 2], [4, 5]]) >>> matrix[1:3, 1:3] array([[5, 6], [8, 9]]) >>> print(matrix.sum()) 45 Hopefully the above shows how you could go about performing your task. One thing to note: NumPy arrays shouldn't contain Python objects - instead I'd probably split your tuples into two separate numpy arrays (you could make it a 3d numpy array but that's probably overcomplicating)
🌐
Chegg
chegg.com › engineering › computer science › computer science questions and answers › a) submatrix extraction with numpy write a python function extract_submatrix (matrix, rows_to_remove, cols_to_remove). this function takes the following parameters: - matrix: a 2d numpy array (matrix) of shape (m, n) ( m,n>1). - rows_to_remove: a list of row indices to be removed from the original matrix. - cols_to_remove: a list of column indices to be
Solved a) Submatrix Extraction with NumPy Write a Python | Chegg.com
November 22, 2023 - Example Consider the following matrix: ⎣⎡​15913​261014​371115​481216​⎦⎤​ If you use rows_to_remove =[1,3], cols_to_remove =[0,2], the expected extracted submatrix is: [[2​4​][1012]]​ The prototype of the function is given as follows: def extract_submatrix(matrix, rows_to_remove, cols_to_remove): \# your statements follow #... return submatrix Save your script for this exercise in p1a.py. Hint: you may use np.delete, np.full, np.setdif1d, etc. In this part, you are going to write a function that takes a grayscale image represented by a 2D NumPy array (height × width) and a kernel represented by another 2D NumPy array, and performs convolution on the image using the kernel.
Find elsewhere
🌐
DNMTechs
dnmtechs.com › extracting-submatrix-in-numpy
Extracting Submatrix in Numpy – DNMTechs – Sharing and Storing Technology Knowledge
In Numpy, slicing is done using the colon (:) operator. For example, arr[1:4] will extract elements from index 1 to 3 (exclusive) in the array arr. Submatrix: A submatrix is a matrix that is obtained by selecting a subset of rows and columns from the original matrix.
🌐
Tutorial Reference
tutorialreference.com › python › examples › faq › python-numpy-how-to-extract-submatrix-from-an-array
Python NumPy: How to Extract a Submatrix from a 2D Array | Tutorial Reference
The numpy.ix_() function is particularly useful when you want to construct a submatrix from specific, potentially non-contiguous, rows and columns.
Author: bobbyhadz
🌐
Python
mail.python.org › pipermail › tutor › 2010-July › 077020.html
[Tutor] extract a submatrix
September 5, 2013 - Next message: [Tutor] extract a submatrix · Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] Hello Bala! On Sunday July 11 2010 23:41:14 Bala subramanian wrote: > I have a > matrix of size 550,550. I want to extract only part of this matrix say > first 330 elements, i dnt need the last 220 elements in the matrix. is > there any function in numpy that can do this kind of extraction.
Top answer
1 of 3
2

To optimize the idea would be to minimize the computations once we are inside the loop. So, with that in mind, we would rearrange the rows of the array, sorted by the first column. Then, get the indices that define the boundaries. Finally, start our loop and simply slice for each group to get a submatrix at each iteration. Slicing is virtually free when working with arrays, so that should help us.

Thus, one implementation would be -

a0 = data_mat[:,0]
sidx = a0.argsort()
sd = data_mat[sidx] # sorted data_mat
idx = np.flatnonzero(np.concatenate(( [True], sd[1:,0] != sd[:-1,0], [True] )))
for i,j in zip(idx[:-1], idx[1:]):
    tmp_mat = sd[i:j]
    print tmp_mat

If you are looking to store each submatrix as an array to have a list of arrays as the final output, simply do -

[sd[i:j] for i,j in zip(idx[:-1], idx[1:])]

For sorted data_mat

For a case with data_mat already being sorted as shown in the sample, we could avoid sorting the entire array and directly use the first column, like so -

a0 = data_mat[:,0]
idx = np.flatnonzero(np.concatenate(( [True], a0[1:] != a0[:-1], [True] )))

for i,j in zip(idx[:-1], idx[1:]):
    tmp_mat = data_mat[i:j]
    print(tmp_mat)

Again, to get all those submatrices as a list of arrays, use -

[data_mat[i:j] for i,j in zip(idx[:-1], idx[1:])]

Note that the submatrices that we would get with this one would be in a different order than with the sorting done in the previous approach.


Benchmarking for sorted data_mat

Approaches -

# @Daniel F's soln-2
def split_app(data_mat):
    idx = np.flatnonzero(data_mat[1:, 0] != data_mat[:-1, 0]) + 1
    return np.split(data_mat, idx)

# Proposed in this post
def zip_app(data_mat):
    a0 = data_mat[:,0]
    idx = np.flatnonzero(np.concatenate(( [True], a0[1:] != a0[:-1], [True] )))
    return [data_mat[i:j] for i,j in zip(idx[:-1], idx[1:])]

Timings -

In the sample we had a submatrix of max length 6. So, let's extend to a bigger case keeping it with the same pattern -

In [442]: a = np.random.randint(0,100000,(6*100000,4)); a[:,0].sort()

In [443]: %timeit split_app(a)
10 loops, best of 3: 88.8 ms per loop

In [444]: %timeit zip_app(a)
10 loops, best of 3: 40.2 ms per loop

In [445]: a = np.random.randint(0,1000000,(6*1000000,4)); a[:,0].sort()

In [446]: %timeit split_app(a)
1 loop, best of 3: 917 ms per loop

In [447]: %timeit zip_app(a)
1 loop, best of 3: 414 ms per loop
2 of 3
2

You can do this with boolean indexing.

unique_ids = np.unique(data_mat[:, 0])
masks = np.equal.outer(unique_ids, data_mat[:, 0])
for mask in masks:
    tmp_mat = data_mat[mask]
    # do something with tmp_mat ...
    print(tmp_mat)
🌐
PyTorch Forums
discuss.pytorch.org › t › extracting-a-submatrix-from-a-matrix › 186793
Extracting a submatrix from a matrix - PyTorch Forums
August 21, 2023 - Given a 2-d tensor x, 1-d index tensors I and J, I knew of the way of extracting submatrix as x[I][:, J] which works. But at python - Numpy extract submatrix - Stack Overflow I also found for NumPy a way of x[I[:, None]…
🌐
StrataScratch
stratascratch.com › blog › numpy-array-slicing-in-python
NumPy Array Slicing in Python - StrataScratch
March 1, 2024 - The matrix[:2, :3] slice selects the first two rows and the first three columns, creating a submatrix. Let’s see the code. import numpy as np # Create a 2D array (3x4 matrix) matrix = np.array([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]) # Select the second row row2 = matrix[1, :] print("Second row:", row2) # Select the third column col3 = matrix[:, 2] print("Third column:", col3) # Select a submatrix (first two rows, first three columns) submatrix = matrix[:2, :3] print("Submatrix of first two rows and three columns:", submatrix)
Top answer
1 of 7
122

To answer this question, we have to look at how indexing a multidimensional array works in Numpy. Let's first say you have the array x from your question. The buffer assigned to x will contain 16 ascending integers from 0 to 15. If you access one element, say x[i,j], NumPy has to figure out the memory location of this element relative to the beginning of the buffer. This is done by calculating in effect i*x.shape[1]+j (and multiplying with the size of an int to get an actual memory offset).

If you extract a subarray by basic slicing like y = x[0:2,0:2], the resulting object will share the underlying buffer with x. But what happens if you acces y[i,j]? NumPy can't use i*y.shape[1]+j to calculate the offset into the array, because the data belonging to y is not consecutive in memory.

NumPy solves this problem by introducing strides. When calculating the memory offset for accessing x[i,j], what is actually calculated is i*x.strides[0]+j*x.strides[1] (and this already includes the factor for the size of an int):

x.strides
(16, 4)

When y is extracted like above, NumPy does not create a new buffer, but it does create a new array object referencing the same buffer (otherwise y would just be equal to x.) The new array object will have a different shape then x and maybe a different starting offset into the buffer, but will share the strides with x (in this case at least):

y.shape
(2,2)
y.strides
(16, 4)

This way, computing the memory offset for y[i,j] will yield the correct result.

But what should NumPy do for something like z=x[[1,3]]? The strides mechanism won't allow correct indexing if the original buffer is used for z. NumPy theoretically could add some more sophisticated mechanism than the strides, but this would make element access relatively expensive, somehow defying the whole idea of an array. In addition, a view wouldn't be a really lightweight object anymore.

This is covered in depth in the NumPy documentation on indexing.

Oh, and nearly forgot about your actual question: Here is how to make the indexing with multiple lists work as expected:

x[[[1],[3]],[1,3]]

This is because the index arrays are broadcasted to a common shape. Of course, for this particular example, you can also make do with basic slicing:

x[1::2, 1::2]
2 of 7
70

As Sven mentioned, x[[[0],[2]],[1,3]] will give back the 0 and 2 rows that match with the 1 and 3 columns while x[[0,2],[1,3]] will return the values x[0,1] and x[2,3] in an array.

There is a helpful function for doing the first example I gave, numpy.ix_. You can do the same thing as my first example with x[numpy.ix_([0,2],[1,3])]. This can save you from having to enter in all of those extra brackets.

🌐
NumPy
numpy.org › doc › 2.0 › user › numpy-for-matlab-users.html
NumPy for MATLAB users — NumPy v2.0 Manual
import numpy as np from scipy import ... “matrix” that the arguments are two-dimensional entities. Submatrix: Assignment to a submatrix can be done with lists of indices using the ix_ command....
Top answer
1 of 1
3

Listed in this post is a generic approach to get a list of submatrices with given shape. Based on the order of submatrices being row (C-style) or column major (fortran-way), you would have two choices. Here's the implementation with np.reshape , np.transpose and np.array_split -

def split_submatrix(x,submat_shape,order='C'):
    p,q = submat_shape      # Store submatrix shape
    m,n = x.shape

    if np.any(np.mod(x.shape,np.array(submat_shape))!=0):
        raise Exception('Input array shape is not divisible by submatrix shape!')

    if order == 'C':
        x4D = x.reshape(-1,p,n/q,q).transpose(0,2,1,3).reshape(-1,p,q)
        return np.array_split(x4D,x.size/(p*q),axis=0)

    elif order == 'F':
        x2D = x.reshape(-1,n/q,q).transpose(1,0,2).reshape(-1,q)
        return np.array_split(x2D,x.size/(p*q),axis=0)

    else:
        print "Invalid output order."
        return x

Sample run with a modified sample input -

In [201]: x
Out[201]: 
array([[5, 2, 5, 6, 5, 6, 1, 5],
       [1, 1, 8, 4, 4, 5, 2, 5],
       [4, 1, 6, 5, 6, 4, 6, 1],
       [5, 3, 7, 0, 5, 8, 6, 5],
       [7, 7, 0, 6, 5, 2, 5, 4],
       [3, 4, 2, 5, 0, 7, 5, 0]])

In [202]: split_submatrix(x,(3,4))
Out[202]: 
[array([[[5, 2, 5, 6],
         [1, 1, 8, 4],
         [4, 1, 6, 5]]]), array([[[5, 6, 1, 5],
         [4, 5, 2, 5],
         [6, 4, 6, 1]]]), array([[[5, 3, 7, 0],
         [7, 7, 0, 6],
         [3, 4, 2, 5]]]), array([[[5, 8, 6, 5],
         [5, 2, 5, 4],
         [0, 7, 5, 0]]])]

In [203]: split_submatrix(x,(3,4),order='F')
Out[203]: 
[array([[5, 2, 5, 6],
        [1, 1, 8, 4],
        [4, 1, 6, 5]]), array([[5, 3, 7, 0],
        [7, 7, 0, 6],
        [3, 4, 2, 5]]), array([[5, 6, 1, 5],
        [4, 5, 2, 5],
        [6, 4, 6, 1]]), array([[5, 8, 6, 5],
        [5, 2, 5, 4],
        [0, 7, 5, 0]])]