Bastian
Bastian

Reputation: 938

How to numpy.nan*0=0

I would like to have python make the product

numpy.nan*0

return 0 (instead of nan), but e.g.

numpy.nan*4

still return nan.

My application: I have some numpy matrices which I am multiplying with one another. These contain many nan entries, and plenty of zeros. The nans always represent unknown, but finite values which are known to become zero when multiplied with zero. So I would like A*B return [1,nan],[nan,1] in the following example:

import numpy as np
A=np.matrix('1 0; 0 1')
B=np.matrix([[1, np.nan],[np.nan, 1]])

Is this possible?

Many thanks

Upvotes: 1

Views: 3177

Answers (2)

MB-F
MB-F

Reputation: 23647

I don't think it is possible to override the behavior of nan * 0 in numpy directly because that multiplication is performed at a very low level.

However, you can provide your own Python class with the desired multiplication behavior, but be warned: This will seriously kill performance.

import numpy as np


class MyNumber(float):
    def __mul__(self, other):
        if other == 0 and np.isnan(self) or self == 0 and np.isnan(other):
            return 0.0
        return float(self) * other

def convert(x):
    x = np.asmatrix(x, dtype=object)  # use Python objects as matrix elements
    x.flat = [MyNumber(i) for i in x.flat]  # convert each element to MyNumber
    return x


A = convert([[1, 0], [0, 1]])
B = convert([[1, np.nan], [np.nan, 1]])

print(A * B)
# [[1.0 nan]
#  [nan 1.0]]

Upvotes: 0

davide
davide

Reputation: 325

You can use the numpy function numpy.nan_to_num()

import numpy as np
A = np.matrix('1 0; 0 1')
B = np.matrix([[1, np.nan],[np.nan, 1]])
C = np.nan_to_num(A) * np.nan_to_num(B)

The outcome will be [[1., 0.], [0., 1.]].

Upvotes: 4

Related Questions