2

This question is a follow-up of a previous post of mine:

Multiply each column of a numpy array with each value of another array.

Suppose i have the following arrays:

In [252]: k
Out[252]: 
array([[200, 800, 400, 1600],
       [400, 1000, 800, 2000],
       [600, 1200, 1200,2400]])

In [271]: f = np.array([[100,50],[200,100],[300,200]])

In [272]: f
Out[272]: 
array([[100,  50],
       [200, 100],
       [300, 200]])

How can i subtract f from k to obtain the following?

In [252]: g
Out[252]: 
array([[100, 750, 300, 1550],
       [200, 900, 600, 1900],
       [300, 1000, 900,2200]])

Ideally, i would like to make the subtraction in as fewer steps as possible and in concert with the solution provided in my other post, but any solution welcome.

2 Answers 2

1

You can use np.tile, like this:

In [1]: k - np.tile(f, (1, 2))
Out[1]: 
array([[ 100,  750,  300, 1550],
       [ 200,  900,  600, 1900],
       [ 300, 1000,  900, 2200]])

Also, if you happen to know for sure that each dimension of f evenly divides the corresponding dimension of k (which I assume you must, for your desired subtraction to make sense), then you could generalize it slightly:

In [2]: k - np.tile(f, np.array(k.shape) // np.array(f.shape))
Out[2]: 
array([[ 100,  750,  300, 1550],
       [ 200,  900,  600, 1900],
       [ 300, 1000,  900, 2200]])
Sign up to request clarification or add additional context in comments.

4 Comments

np.tile has the disadvantage, that it creates a new array in memory. Better use broadcasting, if possible.
@Daniel See my comment on your answer. I didn't think it was worth downvoting your answer because it's a good alternative, but I do think your comment is mistaken. np.tile is likely to be a more efficient way to do it.
my solution is always more speed and memory efficient, but may be not as clear as yours.
@Daniel We may disagree about it. But I still think your answer is a good one regardless.
0

You can reshape k, to fit f in two dimensions, and use broadcasting:

>>> g = (k.reshape(f.shape[0], -1, f.shape[1]) - f[:, None, :]).reshape(k.shape)

array([[ 100,  750,  300, 1550],
       [ 200,  900,  600, 1900],
       [ 300, 1000,  900, 2200]])

2 Comments

Note that the use of np.newaxis / None dimension expansion is dynamically creating a new array. reshape may also create an entire copy of the array it is reshaping, and it is notoriously difficult to know precisely in what cases reshape will result in a view rather than a copy. Overall, I'd say this approach probably is likely to use more memory than np.tile for large arrays.
Please, don't provide false information. Broadcasting never creates copies; and reshape only in rare conditions, with splitting one dimension in two is never one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.