简体   繁体   中英

Division with numpy matrices that might result in nan

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?

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

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)

ie 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.  ]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM