1 回答
TA贡献1783条经验 获得超4个赞
我将从一个更简单的示例开始,以便更好地理解:
b = np.ma.masked_where(np.arange(20)>-1,np.arange(20))
#b: [-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --]
#b.data: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
c = np.zeros(b.shape)
#c: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
d = np.zeros(b.shape)
#d: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
c += b
#c: [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.]
d = d + b
#d: [-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --]
#d.data: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
第一个操作c += b是就地操作。换句话说,它等效于c = type(c).__iadd__(c, b)which 根据 的类型进行加法c,这不是屏蔽数组,因此 的数据用作b未屏蔽的。
另一方面,d = d + b等同于d = np.MaskedArray.__add__(d, b)(更具体地说,由于屏蔽数组是 ndarray 的子类,它使用__radd__)并且不是就地赋值。这意味着它创建一个新对象并在添加时使用等式右侧的更宽类型,因此将 d (这是一个未屏蔽的数组)转换为屏蔽数组(因为它是一个屏蔽数组),因此加法使用b有效仅值(在本例中没有值,因为所有元素都b被屏蔽且无效)。这会产生一个掩码数组,其掩码与数据保持不变时d相同。bd
这种行为差异不是 Numpy 特有的,也适用于 python 本身。OP 问题中提到的案例具有类似的行为,正如@alaniwi 在评论中提到的那样,带有掩码的布尔索引a并不是该行为的基础。使用a屏蔽b, ,c和的元素d只是限制对被屏蔽元素的赋值a(而不是数组的所有元素),仅此而已。
为了使事情更有趣,实际上更清晰,让我们切换右侧的b和的位置:d
e = np.zeros(b.shape)
#e: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
e = b + e
#e: [-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --]
#e.data: [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.]
请注意,与 类似d = d + b,右侧使用掩码数组__add__函数,因此输出是一个掩码数组,但由于您要添加e到b(aka e = np.MaskedArray.__add__(b, e)),因此返回的掩码数据b,而在 中d = d + b,您将添加b到d和数据d被退回。
添加回答
举报