1

关于 numpy 数组的 numpy 操作中的掩码数组的文档中:

numpy.ma 模块带有大多数 ufunc 的特定实现。每当输入被屏蔽或超出有效域时,具有有效域(例如 log 或 divide)的一元和二元函数都会返回屏蔽常量:例如:

ma.log([-1, 0, 1, 2])
masked_array(data = [-- -- 0.0 0.69314718056],
             mask = [ True  True False False],
       fill_value = 1e+20)

我的问题是,对于我的计算,我需要知道这些无效操作是在哪里产生的。具体来说,我想要这个:

ma.log([-1, 0, 1, 2])
masked_array(data = [np.nan -- 0.0 0.69314718056],
             mask = [ True  True False False],
       fill_value = 1e+20)

冒着这个问题是对话性的风险,我的主要问题是:

masked_array在计算出的无效值(那些“固定”的值fix_invalid,如 np.nan 和 np.inf)没有变成(并与)掩码值合并的情况下,有什么好的解决方案?

我目前的解决方案是计算函数masked_array.data,然后用原始掩码重建掩码数组。但是,我正在编写一个应用程序,它将用户的任意函数映射到许多不同的数组上,其中一些被屏蔽,而另一些则不是,我希望避免只为屏蔽数组使用特殊处理程序。此外,这些数组在 MISSING、NaN 和 Inf 之间有区别,这很重要,因此我不能只使用带有np.nans 的数组而不是masked值。


此外,如果有人对为什么存在这种行为有任何看法,我想知道。fix_invalid在同一个操作中出现这种情况似乎很奇怪,因为对未屏蔽值的操作结果的有效性实际上是用户的责任,用户可以选择使用该功能“清理” 。

此外,如果有人对 numpy 中缺失值的进展有任何了解,请分享,因为最早的帖子是 2011-2012 年的,当时的争论从未产生任何结果。


编辑:2017-10-30

添加到 hpaulj 的答案;具有修改域的日志函数的定义对 numpy 命名空间中的日志行为有副作用。

In [1]: import numpy as np

In [2]: np.log(np.ma.masked_array([-1,0,1,2],[1,0,0,0]))
/home/salotz/anaconda3/bin/ipython:1: RuntimeWarning: divide by zero encountered in log
  #!/home/salotz/anaconda3/bin/python
/home/salotz/anaconda3/bin/ipython:1: RuntimeWarning: invalid value encountered in log
  #!/home/salotz/anaconda3/bin/python
Out[2]: 
masked_array(data = [-- -- 0.0 0.6931471805599453],
             mask = [ True  True False False],
       fill_value = 1e+20)

In [3]: mylog = np.ma.core._MaskedUnaryOperation(np.core.umath.log)

In [4]: np.log(np.ma.masked_array([-1,0,1,2],[1,0,0,0]))
/home/salotz/anaconda3/bin/ipython:1: RuntimeWarning: divide by zero encountered in log
  #!/home/salotz/anaconda3/bin/python
/home/salotz/anaconda3/bin/ipython:1: RuntimeWarning: invalid value encountered in log
  #!/home/salotz/anaconda3/bin/python
Out[4]: 
masked_array(data = [-- -inf 0.0 0.6931471805599453],
             mask = [ True False False False],
       fill_value = 1e+20)

np.log现在具有与 相同的行为mylog,但未np.ma.log更改:

In [5]: np.ma.log(np.ma.masked_array([-1,0,1,2],[1,0,0,0]))
Out[5]: 
masked_array(data = [-- -- 0.0 0.6931471805599453],
             mask = [ True  True False False],
       fill_value = 1e+20)

有没有办法避免这种情况?

使用Python 3.6.2 :: Anaconda custom (64-bit)和 numpy1.12.1

4

1 回答 1

3

只是澄清这里似乎发生了什么

np.ma.log在参数上运行np.log,但它会捕获警告:

In [26]: np.log([-1,0,1,2])
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in log
  #!/usr/bin/python3
/usr/local/bin/ipython3:1: RuntimeWarning: invalid value encountered in log
  #!/usr/bin/python3
Out[26]: array([        nan,        -inf,  0.        ,  0.69314718])

它掩盖了nan-inf值。并且显然将原始值复制到这些data插槽中:

In [27]: np.ma.log([-1,0,1,2])
Out[27]: 
masked_array(data = [-- -- 0.0 0.6931471805599453],
             mask = [ True  True False False],
       fill_value = 1e+20)
In [28]: _.data
Out[28]: array([-1.        ,  0.        ,  0.        ,  0.69314718])

(在 Py3 中运行;numpy 版本 1.13.1)

这种掩蔽行为并非ma.log. 它是由它的类决定的

In [41]: type(np.ma.log)
Out[41]: numpy.ma.core._MaskedUnaryOperation

np.ma.core其中定义了filldomain属性:

log = _MaskedUnaryOperation(umath.log, 1.0,
                        _DomainGreater(0.0))

所以有效域(未屏蔽)>0:

In [47]: np.ma.log.domain([-1,0,1,2])
Out[47]: array([ True,  True, False, False], dtype=bool)

该域掩码or-ed

In [54]: ~np.isfinite(np.log([-1,0,1,2]))
...
Out[54]: array([ True,  True, False, False], dtype=bool)

具有相同的值。

看起来我可以定义一个log不添加自己的域掩码的自定义:

In [58]: mylog = np.ma.core._MaskedUnaryOperation(np.core.umath.log)
In [59]: mylog([-1,0,1,2])
Out[59]: 
masked_array(data = [        nan        -inf  0.          0.69314718],
             mask = False,
       fill_value = 1e+20)

In [63]: np.ma.masked_array([-1,0,1,2],[1,0,0,0])
Out[63]: 
masked_array(data = [-- 0 1 2],
             mask = [ True False False False],
       fill_value = 999999)
In [64]: np.ma.log(np.ma.masked_array([-1,0,1,2],[1,0,0,0]))
Out[64]: 
masked_array(data = [-- -- 0.0 0.6931471805599453],
             mask = [ True  True False False],
       fill_value = 1e+20)
In [65]: mylog(np.ma.masked_array([-1,0,1,2],[1,0,0,0]))
Out[65]: 
masked_array(data = [-- -inf 0.0 0.6931471805599453],
             mask = [ True False False False],
       fill_value = 1e+20)
于 2017-10-27T21:06:23.170 回答