6659081
6659081

Reputation: 401

How to subtract a NumPy array from another one with a condition on the elements of the first one

This question sounds like it may have already been solved, but even though I looked, I couldn't find an answer.

So, I've got a NumPy array that contains zeros in some indices:

a = np.array([[1, 2, 3], [4, 0, 0], [7, 8, 0]])

And another NumPy array, with the same shape, that may or may not contain zeros (it usually doesn't):

b = np.array([[10, 11, 12], [13, 14, 15], [16, 17, 18]])

I need to subtract b from a only where a is not zero.

So, my result should be:

array([[-9, -9, -9],
       [-9, 0, 0],
       [-9, -9, 0]])

Notice that because I'm not subtracting when a is zero, the zeros stay in place.

First, I tried using a mask:

a[a!=0] = -b

But the mask, of course, only returns the elements that are not zero and all the information about the indices is lost, so this fails:

TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions.

Then, I tried using np.subtract with the argument where:

subtraction = np.subtract(a, b, where=a!=0)

But it resulted in this (I assume it's because of the mask created by where):

array([[-9, -9,                  -9],
       [-9, 2314885530817014877, 3183534901137448992],
       [-9, -9,                  80]])

I've also thought of using np.nonzero to get the non-zero indices and then iterate over them and subtract the elements, but my arrays can be quite large and can contain either almost all zeros or almost no zeros, so in the latter case, it could become a expensive operation in terms of time.

Is there a simple way to achieve my desired result?

Upvotes: 2

Views: 4438

Answers (3)

MD4
MD4

Reputation: 19

As you think first, you can performed what you want with a mask:

a[a != 0] = a[a != 0] - b[a != 0]
a
# Output:
array([[-9, -9, -9],
       [-9,  0,  0],
       [-9, -9,  0]])

Upvotes: 0

Darkstar Dream
Darkstar Dream

Reputation: 1859

Well, I found a trick for this. we can convert all non-zero values of a to 1 and we will multiply it with b which will make all values of b to zero at the same index where a values are

a = np.array([[1, 2, 3], [4, 0, 0], [7, 8, 0]])
b = np.array([[10, 11, 12], [13, 14, 15], [16, 17, 18]])

c = a.copy()

# convert all non-zero values to 1
c[c!=0]=1

# match the 0
d = c*b

# now we will subtract d from a
a-d

output

array([[-9, -9, -9],
       [-9,  0,  0],
       [-9, -9,  0]])

Hope it helped :)

Upvotes: 0

Sabil
Sabil

Reputation: 4510

Try this:

import numpy as np

a = np.array([[1, 2, 3], [4, 0, 0], [7, 8, 0]])
b = np.array([[10, 11, 12], [13, 14, 15], [16, 17, 18]])

sub = np.where(a, a-b, a)
print(sub)

Output:

[[-9 -9 -9]
 [-9  0  0]
 [-9 -9  0]]

Upvotes: 3

Related Questions