首页 > 解决方案 > python中具有合理NaN行为的经验CDF函数

问题描述

我正在寻找计算 ECDF 并正在使用这个 statsmodels 函数:

from statsmodels.distributions.empirical_distribution import ECDF

乍一看还不错:

ECDF(np.array([0,1,2,3, 3, 3]))(np.array([0,1,2,3, 3,3]))
array([0.16666667, 0.33333333, 0.5       , 1.        , 1.        ,
       1.        ])

但是, nan 似乎被视为无穷大:


>>> x = np.array([0,1,2,3, np.nan, np.nan])
>>> ECDF(x)(x)
array([0.16666667, 0.33333333, 0.5       , 0.66666667, 1.        ,
       1.        ])

如同:

np.array([0,1,2,3, np.inf, np.inf])
ECDF(x)(x)
array([0.16666667, 0.33333333, 0.5       , 0.66666667, 1.        ,
       1.        ])

与 R 比较:

> x <- c(0,1,2,3,NA,NA)
> x
[1]  0  1  2  3 NA NA
> ecdf(x)(x)
[1] 0.25 0.50 0.75 1.00   NA   NA

什么是 ecdf 的标准 python 函数,它是 nan 感知的?

像这样的热接线似乎不起作用:

def ecdf(x):
  return np.where(~np.isfinite(x),
                  np.full_like(x, np.nan),
                  ECDF(x[np.isfinite(x)])(x[np.isfinite(x)]))

ecdf(x)
    ECDF(x[np.isfinite(x)])(x[np.isfinite(x)]))
  File "<__array_function__ internals>", line 6, in where
ValueError: operands could not be broadcast together with shapes (7,) (7,) (4,) 

                  

标签: pythonnumpy

解决方案


您可以使用掩码数组:

import numpy.ma as ma

def ecdf(x):
  return np.where(np.isnan(x),
                  np.full_like(x, np.nan),
                  ECDF(ma.array(x, mask=np.isnan(x)).compressed(), "right")(ma.array(x, mask=np.isnan(x))),
)

>>> ecdf(x)
array([0.25, 0.5 , 0.75, 1.  ,  nan,  nan])

匹配 R 原生的功能。


推荐阅读