to answer your question s is only a 1d array ... (even if you did actually transpose it ... which you did not)

>>> u,s,v = linalg.svd(A)
>>> s
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])
>>>

for selecting a submatrix I think this does what you want ... there may be a better way

>>> rows = range(10,15)
>>> cols = range(5,8)
>>> A[rows][:,cols]
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

or probably better

>>> A[15:32, 2:7]
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])
Answer from Joran Beasley on Stack Overflow
🌐
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)
Discussions

python - Numpy extract submatrix - Stack Overflow
You submatrix is not a contiguous region, some rows and/or columns have been removed within this region, then you must build a mesh of valid cells, and use it as a mask. Fortunately this is the purpose of numpy:ix_, e.g. More on stackoverflow.com
🌐 stackoverflow.com
python - How to create a sub-matrix in numpy - Stack Overflow
note that the submatrix you get is a new copy, not a view of the original mat. ... Sign up to request clarification or add additional context in comments. ... import numpy as np a = np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) cols = np.array([True, False, True]) rows = ... More on stackoverflow.com
🌐 stackoverflow.com
June 16, 2014
arrays - Update submatrix with R-like or MATLAB-like syntax in NumPy and Python - Stack Overflow
I was a R user and I am learning Python (numpy in particular), but I cannot perform a simple task of updating a submatrix in Python which can be very easily done in R. So I have 2 problems. First... More on stackoverflow.com
🌐 stackoverflow.com
May 24, 2017
python - Replace sub part of matrix by another small matrix in numpy - Stack Overflow
I am new to Numpy and want to replace part of a matrix. More on stackoverflow.com
🌐 stackoverflow.com
🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.block.html
numpy.block — NumPy v2.5 Manual
Assemble an nd-array from nested lists of blocks · Blocks in the innermost lists are concatenated (see concatenate) along the last dimension (-1), then these are concatenated along the second-last dimension (-2), and so on until the outermost list is reached
Find elsewhere
Top answer
1 of 1
1

For part 1, from NumPy for MATLAB Users, there are examples showing both read-only and mutable access to arbitrary slices.

The read-only pattern is similar to what you already describe, A[:, m][m]. This slices the columns first, then the rows, and provides a read-only view of the returned data.

To obtain clean indices for mutating the sub-array, a convenience function is provided, np.ix_. It will stitch together its arguments into an R-like or MATLAB-like slice:

indxs = np.ix_([1,3], [1,3])
A[indxs] = B

The reason behind this is that NumPy follows certain shape-conformability rules (called "broadcasting" rules) about how to infer the shapes you intended based on the shapes present in the data. When NumPy does this for a row index and column index pair, it tries to pair them up element-wise.

So A[[1, 3], [1, 3]] under NumPy's chosen conventions, is interpreted as "Fetch for me the value of A at index (1,1) and at index (3,3)." Which is different than the conventions for this same syntax in MATLAB, Octave, or R.

If you want to get around this manually, without np.ix_, you still can, but you must write down your indices to take advantage of NumPy's broadcasting rules. What this means is you have to give NumPy a reason to believe that you want a 2x2 grid of indices instead of a 1x2 list of two specific points.

You can trick it into believing this by making your row entries into lists themselves: rows = [[1], [3]]. Now when NumPy examines the shape of this (1 x 2 instead of 1 x nothing) it will say, 'aha, the columns had better also be 1 x 2' and automatically promote the list of columns to match individually with each possible row. That's why this also will work:

A[[[1], [3]], [1, 3]] = B

For the second part of your question, the issue is that you want to let NumPy know that your array of [False, True, False, True] is a boolean array and should not be implicitly cast as any other type of array.

This can be done in many ways, but one easy way is to construct an np.array of your boolean values, and its dtype will be bool:

indxs = np.array([False, True, False, True])
print A[:, indxs][indxs] # remember, this one is read only

A[np.ix_(indxs, indxs)] = B

Another helpful NumPy convenience tool is np.s_, which is not a function (it is an instance of numpy.lib.index_tricks.IndexExpression) but can be used kind of like one.

np.s_ allows you to use the element-getting syntax (called getitem syntax in Python, after the __getitem__ method that any new-style class instances will have). By way of example:

In [60]: np.s_[[1,3], [1,3]]
Out[60]: ([1, 3], [1, 3])

In [61]: np.s_[np.ix_([1,3], [1,3])]
Out[61]: 
(array([[1],
       [3]]), array([[1, 3]]))

In [62]: np.s_[:, [1,3]]
Out[62]: (slice(None, None, None), [1, 3])

In [63]: np.s_[:, :]
Out[63]: (slice(None, None, None), slice(None, None, None))

In [64]: np.s_[-1:1:-2, :]
Out[64]: (slice(-1, 1, -2), slice(None, None, None))

So np.s_ basically just mirrors back to what the slice index object will look like if you were to place it inside the square brackets in order to access some array's data.

In particular, the first two of these np.s_ examples shows you the difference between plain A[[1,3], [1,3]] and the use of np.ix_([1,3], [1,3]) and how they result in different slices.

🌐
Towards Data Science
towardsdatascience.com › home › latest › two cool features of python numpy: mutating by slicing and broadcasting
Two cool features of Python NumPy: Mutating by slicing and Broadcasting | Towards Data Science
January 16, 2025 - It turns out that if you use simple slicing/indexing with NumPy to create a sub-array, the sub-array actually points to the main array. Simply put, the in-memory diagram looks like, Therefore, if the sliced array is changed, it affects the parent array too. This could be a useful feature to propagate the desired chain up the food chain but sometimes could also be a nuisance where you to keep the main data set immutable and effect your changes on the subset only.
🌐
IncludeHelp
includehelp.com › python › numpy-extract-submatrix.aspx
Python - NumPy: Extract Submatrix
January 23, 2023 - # Import numpy import numpy as np # Creating a numpy array arr = np.arange(16).reshape(4,4) # Display original array print("Original Matrix:\n",arr,"\n") # Creating a submatrix res = arr[np.ix_([0,3],[0,3])] # Display result print("Created Submatrix:\n",res,"\n")
🌐
NumPy
numpy.org › doc › 2.0 › user › numpy-for-matlab-users.html
NumPy for MATLAB users — NumPy v2.0 Manual
Submatrix: Assignment to a submatrix can be done with lists of indices using the ix_ command.
🌐
IncludeHelp
includehelp.com › python › how-to-replace-sub-part-of-matrix-by-another-small-matrix-in-numpy.aspx
Python - How to replace sub part of matrix by another small matrix in NumPy?
# Import numpy import numpy as np # Creating an array arr = np.ones((5,5)) # Display Original matrix print("Original matrix:\n",arr,"\n") # Creating a small matrix small = np.array([[ 0.1, 0.2],[ 0.3, 0.4]]) # Display small matrix print("Small matrix:\n",small,"\n") # replacing a part of big matrix with small matrix arr[3:5, 3:5] = small # Display result print("Result:\n",arr)
🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.take.html
numpy.take — NumPy v2.5 Manual
Take elements from an array along an axis · When axis is not None, this function does the same thing as “fancy” indexing (indexing arrays using arrays); however, it can be easier to use if you need elements along a given axis. A call such as np.take(arr, indices, axis=3) is equivalent ...
🌐
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]]) ...
🌐
Bobby Hadz
bobbyhadz.com › blog › numpy-extract-submatrix-in-python
Numpy: How to extract a Submatrix from an array | bobbyhadz
Copied!import numpy as np arr = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) print(arr) print('-' * 50) submatrix = arr[np.ix_([0, 3], [1, 3])] # [[ 2 4] # [14 16]] print(submatrix)
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]])]