Jsevillamol
Jsevillamol

Reputation: 2563

Stacking numpy arrays with padding

I have a list of 32 numpy arrays, each of which has shape (n, 108, 108, 2), where n is different in each array. I want to stack all of them to create a numpy array of shape (32, m, 108, 108, 2), where m is the maximum among the ns, and the shorter arrays are padded with zeros.

How do I do this?

I asked something similar yesterday, but the answers there seem to break when using deep arrays like in my case.

Concretely, I went with this solution in the end, which produced the cleanest code:

data = np.column_stack(zip_longest(*data, fillvalue=0))

But now it is throwing this error:

ValueError: setting an array element with a sequence.

Upvotes: 5

Views: 6233

Answers (4)

madracoon
madracoon

Reputation: 23

A = np.ones((4,3))


border_top_bottom = np.zeros((A.shape[1])).reshape(1,A.shape[1])
print(np.vstack([border_top_bottom,A,border_top_bottom]))

temp = np.vstack([border_top_bottom,A,border_top_bottom])

border_right_left = np.zeros((temp.shape[0])).reshape(temp.shape[0],1)
print(np.hstack([np.hstack([border_right_left,temp,border_right_left])]))

Upvotes: 0

D.Shaulskii
D.Shaulskii

Reputation: 73

In my case I needed to stack images with different width and padded with zeros to the left side. for me this works well:

np.random.seed(42)
image_batch = []
for i in np.random.randint(50,500,size=10):
image_batch.append(np.random.randn(32,i))
for im in image_batch:
    print(im.shape)

output: (32, 152) (32, 485) (32, 398) (32, 320) (32, 156) (32, 121) (32, 238) (32, 70) (32, 152) (32, 171)

def stack_images_rows_with_pad(list_of_images):
    func = lambda x: np.array(list(zip_longest(*x, fillvalue=0))) # applied row wise
    return np.array(list(map(func, zip(*list_of_images)))).transpose(2,0,1)

res = stack_images_rows_with_pad(image_batch)

for im in rez:
    print(im.shape)

output: (32, 485) (32, 485) (32, 485) (32, 485) (32, 485) (32, 485) (32, 485) (32, 485) (32, 485) (32, 485)

Upvotes: 4

Jsevillamol
Jsevillamol

Reputation: 2563

I have found a godly answer in this webpage.

The pad_sequences function is exactly what I needed.

from tensorflow.python.keras.preprocessing.sequence import pad_sequences
result = pad_sequences(imgs, padding='post')

Upvotes: 4

Rocky Li
Rocky Li

Reputation: 5958

Try this:

# Create matrices with random first axis length.
depth = np.random.randint(3,20,size=32)
l = []
lmax = 0
for i in depth:
    l.append(np.ones((i,10,10,2)))
    lmax = i if i > lmax else lmax

# Join the matrices:
new_l = []
for m in l:
    new_l.append(np.vstack([m, np.zeros((lmax-m.shape[0], 10, 10, 2))]))
master = np.stack(new_l, axis=0)
master.shape
>>> (32, 19, 10, 10, 2)

I find np.pad almost impossible to work with on higher dimensional matrix - luckily, what you asked was simple, where only one of the dimension will have to extended, such that it's easy to use np.vstack to stack a zeros array that make it conform to a new shape.

Upvotes: 2

Related Questions