'How to extract all K*K submatrix of matrix with or without NumPy?

This is my input:

row=6 col=9

6
9
s b k g s y w g f
r g y e q j j a s
s m s a s z s l e
u s q u e h s s s
g s f h s s e s g
x d r h g y s s s

This is my code:

r=int(input())
c=int(input())
n=min(r,c)
k=3
matrix=[list(map(str,input().split())) for i in range(r)]
t = []
for i in range(0,n-1,k):
  for j in range(0,n-1,k):
    t.append([matrix[i+ii][j+jj] for ii in range(k) for jj in range(k)])
print(t) 

output got:

[['s', 'b', 'k', 'r', 'g', 'y', 's', 'm', 's'], ['g', 's', 'y', 'e', 'q', 'j', 'a', 's', 'z'], ['u', 's', 'q', 'g', 's', 'f', 'x', 'd', 'r'], ['u', 'e', 'h', 'h', 's', 's', 'h', 'g', 'y']]

this code not printing my last 3 columns why? Please help me



Solution 1:[1]

r=int(input())
c=int(input())
n=min(r,c)
k=3
matrix=[list(map(str,input().split())) for i in range(r)]
t = []
a=[]
for i in range(0,r,k):
  for j in range(0,c,k):
    t.append([matrix[i+ii][j+jj] for ii in range(k) for jj in range(k)])
print(t) 

In for loop you used n variable in range. so it will end in the minimum of row and col .That's why you got error..Thank you

Solution 2:[2]

If your matrix size is fixed and is divisible by 3 something like this would do the trick:

for i in range(3):
    for j in range(3):
        print(M[i:i+3,j:j+3])

It also works for bigger matrices but it will leave unused elements if it can't index three elements.

Basically I am indexing the matrix M in both axis. For mor info, please, check Numpy docs

Solution 3:[3]

If a be a NumPy array as:

a = np.array([["s", "b", "k", "g", "s", "y", "w", "g", "f"],
              ["r", "g", "y", "e", "q", "j", "j", "a", "s"],
              ['s', 'm', 's', 'a', 's', 'z', 's', 'l', 'e'],
              ['u', 's', 'q', 'u', 'e', 'h', 's', 's', 's'],
              ['g', 's', 'f', 'h', 's', 's', 'e', 's', 'g'],
              ['x', 'd', 'r', 'h', 'g', 'y', 's', 's', 's']])

Just by one-line NumPy, by little modifying this answer if k=3 --> (3*3):

a.reshape(a.shape[0] // 3, 3, -1, 3).swapaxes(1, 2).reshape(-1, 1, 3 * 3).squeeze()

# [['s' 'b' 'k' 'r' 'g' 'y' 's' 'm' 's']
#  ['g' 's' 'y' 'e' 'q' 'j' 'a' 's' 'z']
#  ['w' 'g' 'f' 'j' 'a' 's' 's' 'l' 'e']
#  ['u' 's' 'q' 'g' 's' 'f' 'x' 'd' 'r']
#  ['u' 'e' 'h' 'h' 's' 's' 'h' 'g' 'y']
#  ['s' 's' 's' 'e' 's' 'g' 's' 's' 's']]

NumPy solution is faster than loops, particularly in case of large array sizes.

Solution 4:[4]

?ut a matrix into square pieces

If we transform the original list into a numpy.array then we can change its strides to get the desired result without touching the data:

import numpy as np
from numpy.lib.stride_tricks import as_strided

matrix = np.array(matrix)
size = matrix.itemsize
rows, cols, step = r, c, k
shape = rows//step, cols//step, step, step
strides = size*cols*step, size*step, size*cols, size

sliced = as_strided(matrix, shape, strides)

sliced is a view into matrix. With rows, cols, step = 6, 9, 3, this array exposes 2×3 squares of the shape 3×3, i.e. sliced.shape == (2, 3, 3, 3). To get a specific square we use the first two indices.

In order to get a list of lists we apply ravel.tolist to each square:

from itertools import chain
t = [x.ravel().tolist() for x in chain(*sliced)]

Another way to get the same is to use split:

# the matrix here is the original list of lists
t = [square.ravel().tolist() 
    for ribbon in np.vsplit(np.array(matrix), rows//step) 
    for square in np.hsplit(ribbon, cols//step)]

Solution 5:[5]

If you are using numpy you can use a sliding window : https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html

It is not fastest method but it is really convenient to use for small matrices! For example if you want to extract 3x3 submatrices from the following matrix a:

import numpy as np
from numpy.lib.stride_tricks import sliding_window_view

a = np.array(
    [
        ["s", "b", "k", "g", "s", "y", "w", "g", "f"],
        ["r", "g", "y", "e", "q", "j", "j", "a", "s"],
        ["s", "m", "s", "a", "s", "z", "s", "l", "e"],
        ["u", "s", "q", "u", "e", "h", "s", "s", "s"],
        ["g", "s", "f", "h", "s", "s", "e", "s", "g"],
        ["x", "d", "r", "h", "g", "y", "s", "s", "s"],
    ]
)
print(sliding_window_view(a, (3, 3)).reshape(-1, 3, 3))

Solution 6:[6]

Frequently you cannot connect to your cluster from a non-whitelisted IP i.e. your Heroku's server IP. To test this - if you have a test env or the project doesn't have any data in it yet, you can open up your cluster to the world, check that the data is being pulled and then enable white-listing and add your server's IP. For maximum security you don'y want to open up your cluster to all connections, instead just add you IP.

Refer to the screen attached. In Atlas panel, go to your cluster, Network Access and click ADD IP ADDRESS. This might look a bit different for you if there are no address there yet - then follow the config wizard.

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hymdal
Solution 2 Gonzalo Donoso
Solution 3
Solution 4
Solution 5 tbeolet
Solution 6 kamil_k