Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #2703 from astrofrog/fix-masked-fill-view

Don't reset the fill_value of a MaskedArray when calling view() with no dtype
  • Loading branch information...
commit 09d82ea2cd0664c7dbbf1b8c17700b0b71a05278 2 parents b209e19 + dadf5b9
@rgommers rgommers authored
View
10 numpy/add_newdocs.py
@@ -4437,10 +4437,12 @@ def luf(lamdaexpr, *args, **kwargs):
Parameters
----------
- dtype : data-type, optional
- Data-type descriptor of the returned view, e.g., float32 or int16.
- The default, None, results in the view having the same data-type
- as `a`.
+ dtype : data-type or ndarray sub-class, optional
+ Data-type descriptor of the returned view, e.g., float32 or int16. The
+ default, None, results in the view having the same data-type as `a`.
+ This argument can also be specified as an ndarray sub-class, which
+ then specifies the type of the returned object (this is equivalent to
+ setting the ``type`` parameter).
type : Python type, optional
Type of the returned view, e.g., ndarray or matrix. Again, the
default None results in type preservation.
View
48 numpy/ma/core.py
@@ -2852,7 +2852,45 @@ def __array_wrap__(self, obj, context=None):
return result
- def view(self, dtype=None, type=None):
+ def view(self, dtype=None, type=None, fill_value=None):
+ """
+ Return a view of the MaskedArray data
+
+ Parameters
+ ----------
+ dtype : data-type or ndarray sub-class, optional
+ Data-type descriptor of the returned view, e.g., float32 or int16.
+ The default, None, results in the view having the same data-type
+ as `a`. As with ``ndarray.view``, dtype can also be specified as
+ an ndarray sub-class, which then specifies the type of the
+ returned object (this is equivalent to setting the ``type``
+ parameter).
+ type : Python type, optional
+ Type of the returned view, e.g., ndarray or matrix. Again, the
+ default None results in type preservation.
+
+ Notes
+ -----
+
+ ``a.view()`` is used two different ways:
+
+ ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view
+ of the array's memory with a different data-type. This can cause a
+ reinterpretation of the bytes of memory.
+
+ ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just
+ returns an instance of `ndarray_subclass` that looks at the same array
+ (same shape, dtype, etc.) This does not cause a reinterpretation of the
+ memory.
+
+ If `fill_value` is not specified, but `dtype` is specified (and is not
+ an ndarray sub-class), the `fill_value` of the MaskedArray will be
+ reset. If neither `fill_value` nor `dtype` are specified (or if
+ `dtype` is an ndarray sub-class), then the fill value is preserved.
+ Finally, if `fill_value` is specified, but `dtype` is not, the fill
+ value is set to the specified value.
+ """
+
if dtype is None:
if type is None:
output = ndarray.view(self)
@@ -2882,7 +2920,13 @@ def view(self, dtype=None, type=None):
pass
# Make sure to reset the _fill_value if needed
if getattr(output, '_fill_value', None) is not None:
- output._fill_value = None
+ if fill_value is None:
+ if dtype is None:
+ pass # leave _fill_value as is
+ else:
+ output._fill_value = None
+ else:
+ output.fill_value = fill_value
return output
view.__doc__ = ndarray.view.__doc__
View
42 numpy/ma/tests/test_core.py
@@ -1554,6 +1554,48 @@ def test_fillvalue_as_arguments(self):
a = identity(3, fill_value=0., dtype=complex)
assert_equal(a.fill_value, 0.)
+ def test_fillvalue_in_view(self):
+ "Test the behavior of fill_value in view"
+
+ # Create initial masked array
+ x = array([1,2,3], fill_value=1, dtype=np.int64)
+
+ # Check that fill_value is preserved by default
+ y = x.view()
+ assert_(y.fill_value==1)
+
+ # Check that fill_value is preserved if dtype is specified and the
+ # dtype is an ndarray sub-class and has a _fill_value attribute
+ y = x.view(MaskedArray)
+ assert_(y.fill_value==1)
+
+ # Check that fill_value is preserved if type is specified and the
+ # dtype is an ndarray sub-class and has a _fill_value attribute (by
+ # default, the first argument is dtype, not type)
+ y = x.view(type=MaskedArray)
+ assert_(y.fill_value==1)
+
+ # Check that code does not crash if passed an ndarray sub-class that
+ # does not have a _fill_value attribute
+ y = x.view(np.ndarray)
+ y = x.view(type=np.ndarray)
+
+ # Check that fill_value can be overriden with view
+ y = x.view(MaskedArray, fill_value=2)
+ assert_(y.fill_value==2)
+
+ # Check that fill_value can be overriden with view (using type=)
+ y = x.view(type=MaskedArray, fill_value=2)
+ assert_(y.fill_value==2)
+
+ # Check that fill_value gets reset if passed a dtype but not a
+ # fill_value. This is because even though in some cases one can safely
+ # cast the fill_value, e.g. if taking an int64 view of an int32 array,
+ # in other cases, this cannot be done (e.g. int32 view of an int64
+ # array with a large fill_value).
+ y = x.view(dtype=np.int32)
+ assert_(y.fill_value == 999999)
+
#------------------------------------------------------------------------------
class TestUfuncs(TestCase):
Please sign in to comment.
Something went wrong with that request. Please try again.