Search code examples
pythonpython-3.xnumpymeaninfinite

numpy mean of complex numbers with infinities


numpy seems to not be a good friend of complex infinities

While we can evaluate:

In[2]: import numpy as np

In[3]: np.mean([1, 2, np.inf])
Out[3]: inf

The following result is more cumbersome:

In[4]: np.mean([1 + 0j, 2 + 0j, np.inf + 0j])
Out[4]: (inf+nan*j)
...\_methods.py:80: RuntimeWarning: invalid value encountered in cdouble_scalars
  ret = ret.dtype.type(ret / rcount)

I'm not sure the imaginary part make sense to me. But please do comment if I'm wrong.

Any insight into interacting with complex infinities in numpy?


Solution

  • Solution

    To compute the mean we divide the sum by a real number. This division causes problems because of type promotion (see below). To avoid type promotion we can manually perform this division separately for the real and imaginary part of the sum:

    n = 3
    s = np.sum([1 + 0j, 2 + 0j, np.inf + 0j])
    mean = np.real(s) / n + 1j * np.imag(s) / n
    print(mean)  # (inf+0j)
    

    Rationale

    The issue is not related to numpy but to the way complex division is performed. Observe that ((1 + 0j) + (2 + 0j) + (np.inf + 0j)) / (3+0j) also results in (inf+nanj).

    The result needs to be split into a real and imagenary part. For division both operands are promoted to complex, even if you divide by a real number. So basically the division is:

     a + bj
    --------
     c + dj
    

    The division operation does not know that d=0. So to split the result into real and imaginary it has to get rid of the j in the denominator. This is done by multiplying numerator and denominator with the complex conjugate:

     a + bj     (a + bj) * (c - dj)     ac + bd + bcj - adj
    -------- = --------------------- = ---------------------
     c + dj     (c + dj) * (c - dj)        c**2 + d**2
    

    Now, if a=inf and d=0 the term a * d * j = inf * 0 * j = nan * j.