Reputation: 3221
How can I divide two numpy matrices A
and B
in python when sometimes the two matrices will have 0 on the same cell?
Basically A[i,j]>=B[i,j]
for all i
, j
. I need to calculate C=A/B
. But sometimes A[i,j]==B[i,j]==0
. And when this happens I need A[i,j]/B[i,j]
to be defined as 0.
Is there a simple pythonic way other than going through all the indexes?
Upvotes: 4
Views: 6339
Reputation: 152587
You can use the where
argument for ufuncs like np.true_divide
:
np.true_divide(A, B, where=(A!=0) | (B!=0))
In case you have no negative values (as stated in the comments) and A >= B
for each element (as stated in the question) you can simplify this to:
np.true_divide(A, B, where=(A!=0))
because A[i, j] == 0
implies B[i, j] == 0
.
For example:
import numpy as np
A = np.random.randint(0, 3, (4, 4))
B = np.random.randint(0, 3, (4, 4))
print(A)
print(B)
print(np.true_divide(A, B, where=(A!=0) | (B!=0)))
[[1 0 2 1]
[1 0 0 0]
[2 1 0 0]
[2 2 0 2]]
[[1 0 1 1]
[2 2 1 2]
[2 1 0 1]
[2 0 1 2]]
[[ 1. 0. 2. 1. ]
[ 0.5 0. 0. 0. ]
[ 1. 1. 0. 0. ]
[ 1. inf 0. 1. ]]
As alternative: Just replace nan
s after the division:
C = A / B # may print warnings, suppress them with np.seterrstate if you want
C[np.isnan(C)] = 0
Upvotes: 4
Reputation: 221504
You could use a mask with np.where
to choose between such a case of A and B being both zeros
and otherwise and put out 0
or an elementwise division respectively -
from __future__ import division # For Python 2.x
mask = (A == B) & (A==0)
C = np.where(mask, 0, A/B)
About the mask creation : (A==B)
would be the mask of all elements that are equal between A
and B
and with (A==0)
we have a mask of all elements that are zero in A
. Thus, with a combined mask of (A == B) & (A==0)
, we have mask of places where both A
and B
are zeros. A more simpler version to do the same task and maybe easier to understand would be to check for zeros in both A
and B
and it would be :
mask = (A==0) & (B==0)
About the use of np.where
, its syntax is :
C = np.where(mask, array1, array2)
i.e. we would select elements for assinging into C
based on the mask. If the corresponding mask element is True
, we pick the corresponding element from array1
, else from array2
. This is done on elementwise level and thus, we have the output C
.
Sample run -
In [48]: A
Out[48]:
array([[4, 1, 4, 0, 3],
[0, 4, 1, 4, 3],
[1, 0, 0, 4, 0]])
In [49]: B
Out[49]:
array([[4, 2, 2, 1, 4],
[2, 1, 2, 4, 2],
[4, 0, 2, 0, 3]])
In [50]: mask = (A == B) & (A==0)
In [51]: np.where(mask, 0, A/B)
Out[51]:
array([[ 1. , 0.5 , 2. , 0. , 0.75],
[ 0. , 4. , 0.5 , 1. , 1.5 ],
[ 0.25, 0. , 0. , inf, 0. ]])
Upvotes: 2