【问题标题】:Numpy: multiplying with NaN values without using nan_to_numNumpy:在不使用 nan_to_num 的情况下与 NaN 值相乘
【发布时间】:2015-03-19 04:13:40
【问题描述】:

我可以使用numpy 对我的程序中的一些操作进行相当多的优化。当我分析一次跑步时,我注意到大部分时间都花在了numpy.nan_to_num。我想进一步改进这一点。

发生的计算类型是两个数组的乘法,其中一个数组可以包含nan 值。我希望这些被视为零,但我不能用零初始化数组,因为nan 稍后有含义并且不能设置为0。有没有一种方法可以进行乘法(和加法)与nan 被视为零?

nan_to_num 文档字符串中,我可以看到生成了一个新数组,这可以解释为什么需要这么长时间。

将 nan 替换为 0,将 inf 替换为有限数。

返回一个数组或标量,将非数字 (NaN) 替换为零,...

nansum 这样用于任意算术运算的函数会​​很棒。

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    以下是一些示例数据:

    import numpy as np
    
    a = np.random.rand(1000, 1000)
    a[a < 0.1] = np.nan    # set some random values to nan
    b = np.ones_like(a)
    

    一种选择是使用 np.where 将结果的值设置为 0,只要您的数组之一等于 NaN:

    result = np.where(np.isnan(a), 0, a * b)
    

    如果您必须对包含 NaN 的数组执行多项操作,您可以考虑使用masked arrays,它提供了一种更通用的方法来处理缺失或无效值:

    masked_a = np.ma.masked_invalid(a)
    
    result2 = masked_a * b
    

    这里,result2 是另一个np.ma.masked_array,其.mask 属性是根据a 中NaN 值的位置设置的。要将其转换回普通的 np.ndarray 并将掩码值替换为 0,您可以使用 .filled() 方法,传入您选择的填充值:

    result_filled = result2.filled(0)
    
    assert np.all(result_filled == result)
    

    【讨论】:

    • 这种masked_invalid 和随后的filled 方法实际上比nan_to_num 花费更长的时间(至少在我的用例中)。
    • 好的,那么使用np.where 怎么样?能给个真实的测试用例吗?
    • 是的。忘记提了。这实际上效果很好(而且速度更快)。
    • 您愿意在您的上下文中扩展 np.where 的作用吗?我有一个诸如(p * np.nan_to_num(s)).sum(axis=3, out=p) 之类的构造,并尝试将其转换为p = np.where(s, 0, s * p).sum(axis=3),但这似乎并没有给出相同的结果。我的转换正确吗?
    • 语法是np.where(condition, val_where_true, val_where_false)。在您的示例中,您希望结果数组的值为 0,只要 s 等于 NaN,而 s * p,只要 s 不等于 NaN。因此:np.where(np.isnan(s), 0, s * p).
    猜你喜欢
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多