sal*_*otz 2 python arrays numpy missing-data masked-array
来自 numpy数组上的 numpy 操作中的屏蔽数组的文档:
numpy.ma 模块附带了大多数 ufunc 的特定实现。每当输入被屏蔽或超出有效域时,具有有效域(例如对数或除法)的一元和二元函数都会返回屏蔽常量:例如:
ma.log([-1, 0, 1, 2])
masked_array(data = [-- -- 0.0 0.69314718056],
mask = [ True True False False],
fill_value = 1e+20)
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,对于我的计算,我需要知道这些无效操作是在哪里产生的。具体来说,我想要这样:
ma.log([-1, 0, 1, 2])
masked_array(data = [np.nan -- 0.0 0.69314718056],
mask = [ True True False False],
fill_value = 1e+20)
Run Code Online (Sandbox Code Playgroud)
冒着这个问题成为对话的风险,我的主要问题是:
masked_array在计算出的无效值(由fix_invalidnp.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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
有办法避免这种情况吗?
使用Python 3.6.2 :: Anaconda custom (64-bit)和 numpy1.12.1
只是澄清一下这里发生了什么
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])
Run Code Online (Sandbox Code Playgroud)
它掩盖了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])
Run Code Online (Sandbox Code Playgroud)
(在 Py3 中运行;numpy 版本 1.13.1)
这种屏蔽行为并非 所独有ma.log。这是由它的类决定的
In [41]: type(np.ma.log)
Out[41]: numpy.ma.core._MaskedUnaryOperation
Run Code Online (Sandbox Code Playgroud)
其中np.ma.core定义了fill和domain属性:
log = _MaskedUnaryOperation(umath.log, 1.0,
_DomainGreater(0.0))
Run Code Online (Sandbox Code Playgroud)
因此有效域(未屏蔽)>0:
In [47]: np.ma.log.domain([-1,0,1,2])
Out[47]: array([ True, True, False, False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
该域掩码or-ed是
In [54]: ~np.isfinite(np.log([-1,0,1,2]))
...
Out[54]: array([ True, True, False, False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
具有相同的值。
看起来我可以定义一个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)
Run Code Online (Sandbox Code Playgroud)