一种新的设计规范 nan_policy
¶
中的许多函数 scipy.stats
有一个名为 nan_policy
它确定函数如何处理包含以下内容的数据 nan
。在本部分中,我们提供了本网站开发人员的指南,说明如何 nan_policy
旨在使用,以确保在将此参数添加到新函数时,我们保持一致的API。
基础API¶
该参数 nan_policy
接受三种可能的字符串: 'omit'
, 'raise'
和 'propagate'
。它们的含义是:
nan_policy='omit'
:忽略出现的nan
在输入中。如果输入包含以下内容,则不生成警告nan
(除非使用nan
删除的值将生成警告)。例如,对于接受单个数组并返回标量(并忽略可能使用的axis
目前):func([1.0, 3.0, np.nan, 5.0], nan_policy='omit')
行为应与以下内容相同:
func([1.0, 3.0, 5.0])
更一般地,对于返回标量的函数,
func(a, nan_policy='omit')
行为应该与func(a[~np.isnan(a)])
。For functions that transform a vector to a new vector of the same size and for which each entry in the output array depends on more than just the corresponding value in the input array 1 (e.g.
scipy.stats.zscore
,scipy.stats.boxcox
whenlmbda
is None),:y = func(a, nan_policy='omit')
行为应与以下内容相同:
nan_mask = np.isnan(a) y = np.empty(a.shape, dtype=np.float64) y[~nan_mask] = func(a[~nan_mask]) y[nan_mask] = np.nan
(通常,
y
可能取决于a
以及关于……的预期行为func
)。换句话说,一个 nan 在输入中给出了相应的 nan 在输出中,但它的存在 nan 不影响非`nan`值的计算。此属性的单元测试应用于测试处理
nan_policy
。对于返回标量并接受两个或多个参数但其值不相关的函数(例如
scipy.stats.ansari
,scipy.stats.f_oneway
),同样的思想也适用于每个输入数组。因此::func(a, b, nan_policy='omit')
行为应与以下内容相同:
func(a[~np.isnan(a)], b[~np.isnan(b)])
对于具有以下项的输入 相关 或 成对的 值(例如
scipy.stats.pearsonr
,scipy.stats.ttest_rel
)建议的行为是省略所有与其相关的值nan
。对于具有两个相关数组输入的函数,这意味着:y = func(a, b, nan_policy='omit')
行为应与以下内容相同:
hasnan = np.isnan(a) | np.isnan(b) # Union of the isnan masks. y = func(a[~hasnan], b[~hasnan])
此类函数的文档字符串应该清楚地说明此行为。
nan_policy='raise'
:提高ValueError
。nan_policy='propagate'
:传播nan
值添加到输出。通常,这意味着只执行函数,而不检查nan
,但是请看例如,这可能会导致意外输出。
nan_policy
与一个 axis
参数¶
这并不令人惊讶--当函数具有 axis
参数。例如,假设, func
将一维数组缩减为标量,并将n-d数组作为一维数组的集合进行处理,并使用 axis
指定要沿其应用缩减的轴的参数。如果是,请说::
func([1, 3, 4]) -> 10.0
func([2, -3, 8, 2]) -> 4.2
func([7, 8]) -> 9.5
func([]) -> -inf
然后::
func([[ 1, nan, 3, 4],
[ 2, -3, 8, 2],
[nan, 7, nan, 8],
[nan, nan, nan, nan]], nan_policy='omit', axis=-1)
必须给出结果::
np.array([10.0, 4.2, 9.5, -inf])
边缘情况¶
一个函数,该函数实现 nan_policy
参数应优雅地处理以下情况 all 输入数组中的值为 nan
。上述基本原则仍然适用:
func([nan, nan, nan], nan_policy='omit')
行为应与以下内容相同:
func([])
实际上,在添加 nan_policy
对于现有函数,发现该函数尚未以定义良好的方式处理这种情况并不少见,可能需要应用一些思想和设计来确保其正常工作。正确的行为(无论是返回 nan
、返回其他值、引发异常或其他内容)将根据具体情况确定。
为什么不 nan_policy
也适用于 inf
?¶
虽然我们在小学里学过“无穷大不是数”,但浮点值 nan
和 inf
在性质上是不同的。这些价值 inf
和 -inf
其行为更像是常规浮点值,而不是 nan
。
我们可以与之相提并论
inf
设置为其他浮点值,并且它的行为符合预期,例如3 < inf
是真的。在大多数情况下,算术在
inf
,例如inf + inf = inf
,-2*inf = -inf
,1/inf = 0
等。许多现有函数与“预期的”一起工作
inf
:np.log(inf) = inf
,np.exp(-inf) = 0
,np.array([1.0, -1.0, np.inf]).min() = -1.0
等。
所以虽然 nan
几乎总是意味着“出了问题”或“缺了什么”, inf
在许多情况下可以被视为有用的浮点值。
它与NumPy也是一致的 nan
不可忽略的功能 inf
::
>>> np.nanmax([1, 2, 3, np.inf, np.nan])
inf
>>> np.nansum([1, 2, 3, np.inf, np.nan])
inf
>>> np.nanmean([8, -np.inf, 9, 1, np.nan])
-inf
多么 not 要实施 nan_policy
¶
在过去(可能是现在),一些人 stats
已处理的功能 nan_policy
通过使用掩码数组掩码 nan
值,然后使用 mstats
子包。此方法的问题在于,掩码数组代码可能会将 inf
设置为掩码值,这是我们不想做的(请参见上文)。这还意味着,如果不小心,返回值将是掩码数组,如果它们以常规数组传递,用户可能会感到惊讶。
脚注
- 1
如果输出的元素仅取决于输入的相应元素(例如
numpy.sin
,scipy.special.gamma
),那么就不需要nan_policy
参数。