James James - 3 months ago 21
Python Question

Padding elements of a numpy array

Lets say that I have the following

numpy array
:

[[1,1,1]
[1,1,1]
[1,1,1]]


And I need to pad each element in the array with a zero on either side (rather then
numpy.pad()
which pads rows and columns). This ends up as follows:

[ [0,1,0,0,1,0,0,1,0]
[0,1,0,0,1,0,0,1,0]
[0,1,0,0,1,0,0,1,0] ]


Is there a more efficient way to do this then creating an empty array and using nested loops?

Note: My preference is as fast and memory light as possible. Individual arrays can be up to 12000^2 elements and I'm working with 16 of them at the same time so my margins are pretty thin in 32 bit

Edit: Should have specified but the padding is not always 1, padding must be variable as I am up-sampling data by a factor dependent on the array with the highest resolution. given 3 arrays with the shapes (121,121) ; (1200,1200) ; (12010,12010) I need to be able to pad the first two arrays to a shape of (12010,12010) (I know that these numbers don't share common factors, this isn't a problem as being within an index or two of the actual location is acceptable, this padding is just needed to get them into the same shape, rounding out the numbers by padding the rows at the ends is acceptable)

Working Solution: an adjustment of @Kasramvd solution does the trick. Here is the code that fits my application of the problem.

import numpy as np

a = np.array([[1, 2, 3],[1, 2, 3], [1, 2, 3]])

print(a)

x, y = a.shape
factor = 3
indices = np.repeat(np.arange(y + 1), 1*factor*2)[1*factor:-1*factor]

a=np.insert(a, indices, 0, axis=1)

print(a)


results in:

[[1 2 3]
[1 2 3]
[1 2 3]]

[[0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0]
[0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0]
[0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0]]

Answer

You can create the related indices with np.repeat based on array's shape, then insert the 0 in that indices.

>>> def padder(arr, n):
...     x, y = arr.shape
...     indices = np.repeat(np.arange(y+1), n*2)[n:-n]
...     return np.insert(arr, indices, 0, axis=1)
... 
>>> 
>>> padder(a, 1)
array([[0, 1, 0, 0, 1, 0, 0, 1, 0],
       [0, 1, 0, 0, 1, 0, 0, 1, 0],
       [0, 1, 0, 0, 1, 0, 0, 1, 0]])
>>> 
>>> padder(a, 2)
array([[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0]])
>>> padder(a, 3)
array([[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]])

Aforementioned approach in one line:

np.insert(a, np.repeat(np.arange(a.shape[1] + 1), n*2)[n:-n], 0, axis=1)