import numpy as np
a = np.array([0.1, 0.2, 0.4, 0.3])
masked_a = np.ma.masked_array(a, [0, 0, 1, 1])
counter = np.zeros(len(a) + 1)
while True:
action = np.random.choice(len(a), p=masked_a)
counter[action] += 1
print(counter / counter.sum())
# [0.09931198 0.20076697 0. 0. 0.69992105]
它不应该返回索引> 3,但是当masked array的最后一个元素为true时,它可能返回index = 4
在numpy的开发版本中的Generator.choice
中也会发生此问题:
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.20.0.dev0+986e533'
In [3]: rng = np.random.default_rng()
In [4]: pm = np.ma.masked_array([0.1, 0.2, 0.4, 0.3], mask=[0, 0, 1, 1])
In [5]: rng.choice(4, p=pm, size=12)
Out[5]: array([4, 4, 4, 0, 4, 1, 4, 0, 0, 4, 4, 4])
之前我添加了“ bug”标签,但这是一个主观判断。 numpy中还有其他函数无法正确处理蒙版数组(或者更好,“正确地”处理,因为“正确性”也可以作为判断调用),因此我们不一定认为这是一个错误。 也许这只是未定义行为的示例,对此问题的简短回答是“不要这样做!”。 但是,如果我们可以引发异常而不是返回无意义的结果,那就更好了。
添加一个对掩码数组的显式检查,如果任何一个值实际上被掩码,都会引发一个错误,这很容易,但这感觉像是一个非常具体的临时修复程序。
Generator.choice
调度到__array_function__
吗? 如果不是,那么可能应该。
如果确实如此,那么我认为我们将其与所有其他“ maskedarray衰减”一起丢弃,因为我们尚未实现__array_function__
错误。
之前我添加了“ bug”标签,但这是一个主观判断。 numpy中还有其他函数无法正确处理蒙版数组(或者更好,“正确地”处理,因为“正确性”也可以作为判断调用),因此我们不一定认为这是一个错误。 也许这只是未定义行为的示例,对此问题的简短回答是“不要这样做!”。 但是,如果我们可以引发异常而不是返回无意义的结果,那就更好了。
添加一个对掩码数组的显式检查,如果任何一个值实际上被掩码,都会引发一个错误,这很容易,但这感觉像是一个非常具体的临时修复程序。
我认为,如果处理不正确,则不应允许传递掩码数组(应该引发异常),但大多数情况下都可以正确运行(除了某些情况下,效果很好)。 可能对生产环境造成潜在问题。
Generator
没有使用__array_function__
Generator
。 尽管许多强制输入的行为均表现为C连续,但在某些情况下,某些功能可能并不总是如此地有效。
如果添加NPY_ARRAY_ENSUREARRAY
则最终会得到一个ndarray已满并且忽略掩码的结果。 很难说这是“正确的”做法。 在@WarrenWeckesser的示例中,最终使用pm=np.array([.1,.2,.3,.4])
作为概率。