我有一个应用程序正在读取netcdf文件中的32位浮点数据,其中使用了默认的netcdf填充值,即9.96920996839e + 36。在应用程序的特定点上,对从输入数据创建的float32类型的掩码数组执行基本缩放(乘法)操作,因此:
x = marr * scale # or, equivalently, x = ma.multiply(marr,scale)
此操作会在乘法过程中遇到溢出问题。警告,大概是因为填充值和比例的乘积超过了32位浮点数的最大值。已知掩蔽阵列中的其他值很小。那么问题是,为什么numpy甚至计算输入数组中屏蔽元素的产品?当然,这些应该被忽略,对吗?
实际上,警告可以被忽略,因为输出数组中的相应值仍然被标记为已屏蔽。但要知道这是一个numpy中的错误还是按照设计的方式工作会很有趣。
下面的代码片段说明了这种行为。
import numpy as np
import numpy.ma as ma
arr = [9.96920996839e+36, 1.123, 2.345, 9.96920996839e+36]
marr = ma.masked_values(np.array(arr, dtype='float32'), 9.96920996839e+36)
x = marr * 128.0
正如可以预料的那样,如果屏蔽数组的类型为float64,则不会出现溢出警告(尽管可能是因为比例因子足够大)。类似地,如果较小的填充值,例如警告消失,则消失。 -1.0e20,用于float32 case。
从表面上看,当使用较大的填充值(非常接近32位f.p.值的最大值)时,numpy似乎无法识别掩码值。
TIA,
菲尔
答案 0 :(得分:2)
唉,不,不。在当前实现中,任何操作都应用于整个数组,然后重新应用掩码。那么问题是,为什么numpy甚至计算输入数组中屏蔽元素的产品?当然,这些应该被忽略,对吗?
我知道这听起来适得其反,但它是替代其他方法的更强大,效率更低的替代方案。最初,仅在适当的域上应用该操作会很有用,但该域的计算可能会非常棘手(pow
存在一些巨大的问题)。此外,额外的测试会破坏已经可怜的表演。
最近引入了一种新方法,其中numpy函数接受可选参数where
,这可能有助于...但是也有关于直接在C级引入对丢失/忽略值的支持的讨论,这可能是要走的路。
答案 1 :(得分:1)
可能是一个错误。上一行有:
np.seterr(divide='ignore', invalid='ignore')
表示它设计用于处理0或NaN的掩码,但不是非常大的值。它应该是:
np.seterr(divide='ignore', invalid='ignore', over='ignore')
也可以处理大掩码值。
请注意,numpy.ma
操作通常对数组中的所有值进行操作,包括屏蔽值;这可能是因为效率和广播问题。