Fnord
Fnord

Reputation: 5875

Expanding a numpy array of matrices with zeros

What's the most efficient way to pad an array of matrices with zeros?

example:

# Lets construct an array of 2 matrices from 3 arrays of vectors
import numpy as np

A = np.array([[0,1,2],[3,4,5]])       # 2 vectors
B = np.array([[6,7,8],[9,10,11]])     # 2 vectors
C = np.array([[12,13,14],[15,16,17]]) # 2 vectors
M = np.dstack((A,B,C))
'''
# Result: array([[[ 0,  6, 12],
                  [ 1,  7, 13],
                  [ 2,  8, 14]],

                 [[ 3,  9, 15],
                  [ 4, 10, 16],
                  [ 5, 11, 17]]]) #
'''

I want to add a column and/or a row of zeros to every matrix element in the array such as:

'''
# Result: array([[[ 0,  6, 12, 0],
              [ 1,  7, 13, 0],
              [ 2,  8, 14, 0],
              [ 0,  0,  0, 0]],

             [[ 3,  9, 15, 0],
              [ 4, 10, 16, 0],
              [ 5, 11, 17, 0]
              [ 0,  0,  0, 0]]]) #
'''

Upvotes: 0

Views: 3979

Answers (2)

hpaulj
hpaulj

Reputation: 231375

np.pad will work, but for this case it is overkill. We can do it directly with:

A sample 3d array (different dimensions make changes more obvious)

In [408]: M=np.arange(2*3*4).reshape((2,3,4))    
In [409]: M
Out[409]: 
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]]])

A blank array of the desired target shape

In [410]: M1=np.zeros((2,4,5),M.dtype)

Copy values from M to the target in the right slice range.

In [411]: M1[:,:-1,:-1]=M
In [412]: M1
Out[412]: 
array([[[ 0,  1,  2,  3,  0],
        [ 4,  5,  6,  7,  0],
        [ 8,  9, 10, 11,  0],
        [ 0,  0,  0,  0,  0]],

       [[12, 13, 14, 15,  0],
        [16, 17, 18, 19,  0],
        [20, 21, 22, 23,  0],
        [ 0,  0,  0,  0,  0]]])

A copy like this is required. There's no way of expanding the size of M itself. pad returns a new array as well, having performed a general version of this allocate and copy. So there isn't much of an efficiency issue.

You could also concatenate (or 'append') a 0 row or column in the right dimensions. But what I've illustrated does it in one step.

Upvotes: 2

Suever
Suever

Reputation: 65430

You're going to want to use numpy.pad to do this. You can use the second input argument to specify the amount to pad before and after the data in each of the dimensions of the array. Then specify a constant padding type where the padding value is 0 (the default).

result = numpy.pad(M, ((0,0),(0,1),(0,1)), 'constant', constant_values=0)
array([[[ 0,  6, 12,  0],
        [ 1,  7, 13,  0],
        [ 2,  8, 14,  0],
        [ 0,  0,  0,  0]],

       [[ 3,  9, 15,  0],
        [ 4, 10, 16,  0],
        [ 5, 11, 17,  0],
        [ 0,  0,  0,  0]]])

Upvotes: 1

Related Questions