Joe Healey
Joe Healey

Reputation: 1252

Coercing numpy arrays to same dimensions

I have 2 matrices, and I want to perform a 'cell-wise' addition, however the matrices aren't the same size. I want to preserve the cells relative positions during the calculation (i.e. their 'co-ordinates' from the top left), so a simple (if maybe not the best) solution, seems to be to pad the smaller matrix's x and y with zeros.

This thread has a perfectly satisfactory answer for concatenating vertically, and this does work with my data, and following the suggestion in the answer, I also threw in the hstack but at the moment, it's complaining that the dimensions (excluding concatenation axis) need to match exactly. Perhaps hstack doesnt work as I anticipate or exactly equivalently to vstack, but I'm at a bit of a loss now.

This is what hstack throws at me, meanwhile vstack seems to have no problem.

ValueError: all the input array dimensions except for the concatenation axis must match exactly

Essentially the code checks which of a pair of matrices is the shorter and/or wider, and then pads the smaller matrix with zeros to match.

Here's the code I have:

import numpy as np
A = np.random.randint(2, size = (3, 7))
B = np.random.randint(2, size = (5, 10))


# If the arrays have different row numbers:
if A.shape[0] < B.shape[0]:                      # Is A shorter than B?
    A = np.vstack((A, np.zeros((B.shape[0] - A.shape[0], A.shape[1]))))
elif A.shape[0] > B.shape[0]:                    # or is A longer than B?
    B = np.vstack((B, np.zeros((A.shape[0] - B.shape[0], B.shape[1]))))

# If they have different column numbers
if A.shape[1] < B.shape[1]:                      # Is A narrower than B?
    A = np.hstack((A, np.zeros((B.shape[1] - A.shape[1], A.shape[0]))))
elif A.shape[1] > B.shape[1]:                    # or is A wider than B?
    B = np.hstack((B, np.zeros((A.shape[1] - B.shape[1], B.shape[0]))))

It's getting late so its possible I've just missed something obvious with hstack but I can't see my logic error at the moment.

Upvotes: 1

Views: 509

Answers (4)

Engineero
Engineero

Reputation: 12908

I think your hstack lines should be of the form

np.hstack((A, np.zeros((A.shape[0], B.shape[1] - A.shape[1]))))

You seem to have the rows and columns swapped.

Upvotes: 1

B. M.
B. M.

Reputation: 18628

Just use np.pad :

np.pad(A,((0,2),(0,3)),'constant') # 2 is 5-3, 3 is 10-7

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

But the 4 pads width must be computed; so an another simple method to pad the 2 array in any case is :

A = np.ones((3, 7),int)
B = np.ones((5, 2),int)

ma,na = A.shape
mb,nb = B.shape
m,n = max(ma,mb) , max(na,nb)

newA = np.zeros((m,n),A.dtype)
newA[:ma,:na]=A

newB = np.zeros((m,n),B.dtype)
newB[:mb,:nb]=B

For :

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

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

Upvotes: 2

SalvadorViramontes
SalvadorViramontes

Reputation: 580

Yes, indeed. You should swap (B.shape[1] - A.shape[1], A.shape[0]) to (A.shape[0], B.shape[1] - A.shape[1]) and so on, because you need to have the same numbers of rows to stack them horizontally.

Upvotes: 1

Khalil Al Hooti
Khalil Al Hooti

Reputation: 4506

Try b[:a.shape[0], :a.shape[1]] = b[:a.shape[0], :a.shape[1]]+a where b the larger array

Example below

import numpy as np

a = np.arange(12).reshape(3, 4)

print("a\n", a)

b = np.arange(16).reshape(4, 4)

print("b original\n", b)

b[:a.shape[0], :a.shape[1]] = b[:a.shape[0], :a.shape[1]]+a


print("b new\n",b)

output

a
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
b original
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
b new
 [[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]
 [12 13 14 15]]

Upvotes: 0

Related Questions