【问题标题】:Operations on numpy masked array gives invalid values masked对 numpy 掩码数组的操作给出了掩码的无效值
【发布时间】:2018-04-09 12:46:59
【问题描述】:

来自关于 numpy operations on numpy arrays 中掩码数组的文档:

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 中缺失值的进展情况,请分享,因为最古老的 posts 是从 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) 和 numpy 1.12.1

【问题讨论】:

    标签: python arrays numpy missing-data masked-array


    【解决方案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])
    

    它掩盖了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)
    

    【讨论】:

    • 从这篇文章中学到了很多,谢谢。老实说,没想到会有办法解决这个问题。此外,我什至没有注意到该示例使用了np.ma.log 函数,我使用np.log 对其进行了测试,但它具有相同的效果。您对mylog 的定义虽然有副作用。我更新了问题以显示这一点并请求一种避免这种情况的方法。
    猜你喜欢
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多