summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/ma/core.py68
-rw-r--r--numpy/ma/tests/test_core.py31
2 files changed, 53 insertions, 46 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index db8bc7d53..77feec335 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -1624,7 +1624,7 @@ def make_mask(m, copy=False, shrink=True, dtype=MaskType):
# Make sure the input dtype is valid.
dtype = make_mask_descr(dtype)
-
+
# legacy boolean special case: "existence of fields implies true"
if isinstance(m, ndarray) and m.dtype.fields and dtype == np.bool_:
return np.ones(m.shape, dtype=dtype)
@@ -2978,11 +2978,30 @@ class MaskedArray(ndarray):
# heuristic it's not bad.) In all other cases, we make a copy of
# the mask, so that future modifications to 'self' do not end up
# side-effecting 'obj' as well.
- if (obj.__array_interface__["data"][0]
+ if (_mask is not nomask and obj.__array_interface__["data"][0]
!= self.__array_interface__["data"][0]):
- _mask = _mask.copy()
+ # We should make a copy. But we could get here via astype,
+ # in which case the mask might need a new dtype as well
+ # (e.g., changing to or from a structured dtype), and the
+ # order could have changed. So, change the mask type if
+ # needed and use astype instead of copy.
+ if self.dtype == obj.dtype:
+ _mask_dtype = _mask.dtype
+ else:
+ _mask_dtype = make_mask_descr(self.dtype)
+
+ if self.flags.c_contiguous:
+ order = "C"
+ elif self.flags.f_contiguous:
+ order = "F"
+ else:
+ order = "K"
+
+ _mask = _mask.astype(_mask_dtype, order)
+
else:
_mask = nomask
+
self._mask = _mask
# Finalize the mask
if self._mask is not nomask:
@@ -3140,45 +3159,6 @@ class MaskedArray(ndarray):
return output
view.__doc__ = ndarray.view.__doc__
- def astype(self, newtype):
- """
- Returns a copy of the MaskedArray cast to given newtype.
-
- Returns
- -------
- output : MaskedArray
- A copy of self cast to input newtype.
- The returned record shape matches self.shape.
-
- Examples
- --------
- >>> x = np.ma.array([[1,2,3.1],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
- >>> print(x)
- [[1.0 -- 3.1]
- [-- 5.0 --]
- [7.0 -- 9.0]]
- >>> print(x.astype(int32))
- [[1 -- 3]
- [-- 5 --]
- [7 -- 9]]
-
- """
- newtype = np.dtype(newtype)
- newmasktype = make_mask_descr(newtype)
-
- output = self._data.astype(newtype).view(type(self))
- output._update_from(self)
-
- if self._mask is nomask:
- output._mask = nomask
- else:
- output._mask = self._mask.astype(newmasktype)
-
- # Don't check _fill_value if it's None, that'll speed things up
- if self._fill_value is not None:
- output._fill_value = _check_fill_value(self._fill_value, newtype)
- return output
-
def __getitem__(self, indx):
"""
x.__getitem__(y) <==> x[y]
@@ -4303,7 +4283,7 @@ class MaskedArray(ndarray):
elif self._mask:
raise MaskError('Cannot convert masked element to a Python int.')
return int(self.item())
-
+
def __long__(self):
"""
Convert to long.
@@ -4314,7 +4294,7 @@ class MaskedArray(ndarray):
elif self._mask:
raise MaskError('Cannot convert masked element to a Python long.')
return long(self.item())
-
+
def get_imag(self):
"""
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index cc447e37e..2a5a65e5c 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -5037,10 +5037,37 @@ def test_ufunc_with_output():
y = np.add(x, 1., out=x)
assert_(y is x)
+
def test_astype():
descr = [('v', int, 3), ('x', [('y', float)])]
- x = array(([1, 2, 3], (1.0,)), dtype=descr)
- assert_equal(x, x.astype(descr))
+ x = array([
+ [([1, 2, 3], (1.0,)), ([1, 2, 3], (2.0,))],
+ [([1, 2, 3], (3.0,)), ([1, 2, 3], (4.0,))]], dtype=descr)
+ x[0]['v'][0] = np.ma.masked
+
+ x_a = x.astype(descr)
+ assert x_a.dtype.names == np.dtype(descr).names
+ assert x_a.mask.dtype.names == np.dtype(descr).names
+ assert_equal(x, x_a)
+
+ assert_(x is x.astype(x.dtype, copy=False))
+ assert_equal(type(x.astype(x.dtype, subok=False)), np.ndarray)
+
+ x_f = x.astype(x.dtype, order='F')
+ assert_(x_f.flags.f_contiguous)
+ assert_(x_f.mask.flags.f_contiguous)
+
+ # Also test the same indirectly, via np.array
+ x_a2 = np.array(x, dtype=descr, subok=True)
+ assert x_a2.dtype.names == np.dtype(descr).names
+ assert x_a2.mask.dtype.names == np.dtype(descr).names
+ assert_equal(x, x_a2)
+
+ assert_(x is np.array(x, dtype=descr, copy=False, subok=True))
+
+ x_f2 = np.array(x, dtype=x.dtype, order='F', subok=True)
+ assert_(x_f2.flags.f_contiguous)
+ assert_(x_f2.mask.flags.f_contiguous)
###############################################################################