Lauren K.
Lauren K.

Reputation: 35

separating 2d numpy array into nxn chunks

How would you separate a 2D numpy array into a nxn chunks?

For example, the following array of shape (4,4):

arr = [[1,2,3,4],
       [5,6,7,8],
       [9,10,11,12],
       [13,14,15,16]]

Transformed to this array, of shape (4,2,2), by subsampling with a different (2x2) array:

new_arr = [[[1,2],
            [5,6]],
           [[3,4],
            [7,8]],
           [[9,10],
            [13,14]],
           [[11,12],
            [15,16]]]

Upvotes: 1

Views: 2535

Answers (5)

Tong Zhou
Tong Zhou

Reputation: 636

You can easily achieve this using just one line with scipy:

import scipy

arr = [[1,2,3,4],
       [5,6,7,8],
       [9,10,11,12],
       [13,14,15,16]]

arr1 = scipy.sparse.bsr_matrix(arr, blocksize=(2,2)).data
print(arr1)

Output:

[[[ 1  2]
  [ 5  6]]

 [[ 3  4]
  [ 7  8]]

 [[ 9 10]
  [13 14]]

 [[11 12]
  [15 16]]]

You can then reshape arr1 as well if needed.

Upvotes: 0

Mercury
Mercury

Reputation: 4181

There is no need to split or anything; the same can be achieved by reshaping and reordering the axes.

result = np.swapaxes(arr.reshape(2, 2, 2, 2), 1, 2).reshape(-1, 2, 2)

Dividing an (N, N) array to (n, n) chunks is also basically a sliding window op with an (n, n) window and a stride of n.

from numpy.lib.stride_tricks import sliding_window_view

result = sliding_window_view(arr, (2, 2))[::2, ::2].reshape(-1, 2, 2)

Upvotes: 0

Shubham Sharma
Shubham Sharma

Reputation: 71707

You can use np.vsplit to split the array into multiple subarrays vertically. Similarly you can use np.hsplit to split the array into multiple subarrays horizontally. To better understand this examine the generalized resample function which makes the use of np.vsplit and np.hsplit methods.

Use this:

def ressample(arr, N):
    A = []
    for v in np.vsplit(arr, arr.shape[0] // N):
        A.extend([*np.hsplit(v, arr.shape[0] // N)])
    return np.array(A)

Example 1: The given 2D array is of shape 4x4 and we want to subsample it into the chunks of shape 2x2.

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12],
                [13, 14, 15, 16]])  
print(ressample(arr, 2)) #--> chunk size 2

Output 1:

[[[ 1  2]
  [ 5  6]]

 [[ 3  4]
  [ 7  8]]

 [[ 9 10]
  [13 14]]

 [[11 12]
  [15 16]]]

Example 2: Consider the given 2D array contains 8 rows and 8 columns. Now we subsample this array into the chunks of shape 4x4.

arr = np.random.randint(0, 10, 64).reshape(8, 8)   
print(ressample(arr, 4)) #--> chunck size 4

Sample Output 2:

[[[8 3 7 5]
  [7 2 6 1]
  [7 9 2 2]
  [3 1 8 8]]

 [[2 0 3 2]
  [2 9 0 8]
  [2 6 3 9]
  [2 4 4 8]]

 [[9 9 1 8]
  [9 1 5 0]
  [8 5 1 2]
  [2 7 5 1]]

 [[7 8 9 6]
  [9 0 9 5]
  [8 9 8 3]
  [7 3 6 3]]]

Upvotes: 1

Mohamed Shabeer kp
Mohamed Shabeer kp

Reputation: 882

You could use hsplit() and vsplit() methods to achieve the above.

import numpy as np

arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])

ls1,ls2 = np.hsplit(arr, 2)
ls1 = np.vsplit(ls1,2)
ls2 = np.vsplit(ls2,2)
ls = ls1 + ls2
result = np.array(ls)

print(result)

>>> 
 [[[ 1  2]
  [ 5  6]]

 [[ 9 10]
  [13 14]]

 [[ 3  4]
  [ 7  8]]

 [[11 12]
  [15 16]]]

print(result.tolist())

>>> [[[1, 2], [5, 6]], [[9, 10], [13, 14]], [[3, 4], [7, 8]], [[11, 12], [15, 16]]]

Upvotes: 0

David
David

Reputation: 8318

You could do the following, and adjust it to your array:

import numpy as np

arr = [[1,2,3,4],
       [5,6,7,8],
       [9,10,11,12],
       [13,14,15,16]]

arr_new = np.array([[arr[i][j:j+2], arr[i+1][j:j+2]] for j in range(len(arr[0])-2) for i in range(len(arr)-2)])
print(arr_new)
print(arr_new.shape)

This gives the following output:

[[[ 1  2]
  [ 5  6]]

 [[ 5  6]
  [ 9 10]]

 [[ 2  3]
  [ 6  7]]

 [[ 6  7]
  [10 11]]]
(4, 2, 2)

Upvotes: 0

Related Questions