-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
BUG, DEP: Fix masked arrays to properly edit views. ( #5558 ) #5580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3259,8 +3259,6 @@ def __setitem__(self, indx, value): | |
_mask[indx] = tuple([True] * nbfields) | ||
else: | ||
_mask[indx] = True | ||
if not self._isfield: | ||
self._sharedmask = False | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume the default here is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any idea why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll start by explaining what is going on and then answer your questions if that is alright. Please forgive me if I go into too much detail and explain the obvious. Good questions by the way. Sorry if my answer gets too long. This particular branch is dealing with the case of a structured array. Suppose for example we have a structured array created like so However, there is no way to know that this masked array came from a structured masked array; so, the Now, why was To directly answer your first question, we can't assume anything about The argument that I am making here is that this one can't assume this is not a view if it is not a field. In other words, we could always be working with a view of another masked array where we want changes propagated to an original and should not be forcing the user's hand here. Additionally, it would be inconsistent to "unshare" the mask as the data remains shared regardless. |
||
|
||
# Get the _data part of the new value | ||
|
@@ -3276,27 +3274,6 @@ def __setitem__(self, indx, value): | |
_mask = self._mask = make_mask_none(self.shape, _dtype) | ||
_mask[indx] = mval | ||
elif not self._hardmask: | ||
# Unshare the mask if necessary to avoid propagation | ||
# We want to remove the unshare logic from this place in the | ||
# future. Note that _sharedmask has lots of false positives. | ||
if not self._isfield: | ||
notthree = getattr(sys, 'getrefcount', False) and (sys.getrefcount(_mask) != 3) | ||
if self._sharedmask and not ( | ||
# If no one else holds a reference (we have two | ||
# references (_mask and self._mask) -- add one for | ||
# getrefcount) and the array owns its own data | ||
# copying the mask should do nothing. | ||
(not notthree) and _mask.flags.owndata): | ||
# 2016.01.15 -- v1.11.0 | ||
warnings.warn( | ||
"setting an item on a masked array which has a shared " | ||
"mask will not copy the mask and also change the " | ||
"original mask array in the future.\n" | ||
"Check the NumPy 1.11 release notes for more " | ||
"information.", | ||
MaskedArrayFutureWarning, stacklevel=2) | ||
self.unshare_mask() | ||
_mask = self._mask | ||
# Set the data, then the mask | ||
_data[indx] = dval | ||
_mask[indx] = mval | ||
|
@@ -4575,7 +4552,7 @@ def put(self, indices, values, mode='raise'): | |
if self._mask is nomask and getmask(values) is nomask: | ||
return | ||
|
||
m = getmaskarray(self).copy() | ||
m = getmaskarray(self) | ||
|
||
if getmask(values) is nomask: | ||
m.put(indices, False, mode=mode) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -394,15 +394,26 @@ def test_copy(self): | |
y1._data.__array_interface__) | ||
self.assertTrue(y1a.mask is y1.mask) | ||
|
||
y2 = array(x1, mask=m) | ||
y2 = array(x1, mask=m3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, the point is that we have generated a masked array in two different ways first using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, what kind of explanation would you like here? Are we looking for just a comment explaining the two use cases? Should I break them into two separate tests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. |
||
self.assertTrue(y2._data.__array_interface__ == x1.__array_interface__) | ||
self.assertTrue(y2._mask.__array_interface__ == m.__array_interface__) | ||
self.assertTrue(y2._mask.__array_interface__ == m3.__array_interface__) | ||
self.assertTrue(y2[2] is masked) | ||
y2[2] = 9 | ||
self.assertTrue(y2[2] is not masked) | ||
self.assertTrue(y2._mask.__array_interface__ != m.__array_interface__) | ||
self.assertTrue(y2._mask.__array_interface__ == m3.__array_interface__) | ||
self.assertTrue(allequal(y2.mask, 0)) | ||
|
||
y2a = array(x1, mask=m, copy=1) | ||
self.assertTrue(y2a._data.__array_interface__ != x1.__array_interface__) | ||
#self.assertTrue( y2a.mask is not m) | ||
self.assertTrue(y2a._mask.__array_interface__ != m.__array_interface__) | ||
self.assertTrue(y2a[2] is masked) | ||
y2a[2] = 9 | ||
self.assertTrue(y2a[2] is not masked) | ||
#self.assertTrue( y2a.mask is not m) | ||
self.assertTrue(y2a._mask.__array_interface__ != m.__array_interface__) | ||
self.assertTrue(allequal(y2a.mask, 0)) | ||
|
||
y3 = array(x1 * 1.0, mask=m) | ||
self.assertTrue(filled(y3).dtype is (x1 * 1.0).dtype) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should note the previous behavior, the new behavior, and the release in which things changed.