<br><br><div class="gmail_quote">On Thu, Jun 30, 2011 at 8:17 AM, Charles R Harris <span dir="ltr">&lt;<a href="mailto:charlesr.harris@gmail.com">charlesr.harris@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br><br><div class="gmail_quote"><div><div></div><div class="h5">On Thu, Jun 30, 2011 at 7:31 AM, Matthew Brett <span dir="ltr">&lt;<a href="mailto:matthew.brett@gmail.com" target="_blank">matthew.brett@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
<br>
On Tue, Jun 28, 2011 at 4:06 PM, Nathaniel Smith &lt;<a href="mailto:njs@pobox.com" target="_blank">njs@pobox.com</a>&gt; wrote:<br>
&gt; Anyway, it&#39;s pretty clear that in this particular case, there are two<br>
&gt; distinct features that different people want: the missing data<br>
&gt; feature, and the masked array feature. The more I think about it, the<br>
&gt; less I see how they can be combined into one dessert topping + floor<br>
&gt; wax solution. Here are three particular points where they seem to<br>
&gt; contradict each other:<br>
...<br>
[some proposals]<br>
<br>
In the interest of making the discussion as concrete as possible, here<br>
is my draft of an alternative proposal for NAs and masking, based on<br>
Nathaniel&#39;s comments.  Writing it, it seemed to me that Nathaniel is<br>
right, that the ideas become much clearer when the NA idea and the<br>
MASK idea are separate.   Please do pitch in for things I may have<br>
missed or misunderstood:<br>
<br>
###############################################<br>
A alternative-NEP on masking and missing values<br>
###############################################<br>
<br>
The principle of this aNEP is to separate the APIs for masking and for missing<br>
values, according to<br>
<br>
* The current implementation of masked arrays<br>
* Nathaniel Smith&#39;s proposal.<br>
<br>
This discussion is only of the API, and not of the implementation.<br>
<br>
**************<br>
Initialization<br>
**************<br>
<br>
First, missing values can be set and be displayed as ``np.NA, NA``::<br>
<br>
    &gt;&gt;&gt; np.array([1.0, 2.0, np.NA, 7.0], dtype=&#39;NA[f8]&#39;)<br>
    array([1., 2., NA, 7.], dtype=&#39;NA[&lt;f8]&#39;)<br>
<br>
As the initialization is not ambiguous, this can be written without the NA<br>
dtype::<br>
<br>
    &gt;&gt;&gt; np.array([1.0, 2.0, np.NA, 7.0])<br>
    array([1., 2., NA, 7.], dtype=&#39;NA[&lt;f8]&#39;)<br>
<br>
Masked values can be set and be displayed as ``np.MASKED, MASKED``::<br>
<br>
    &gt;&gt;&gt; np.array([1.0, 2.0, np.MASKED, 7.0], masked=True)<br>
    array([1., 2., MASKED, 7.], masked=True)<br>
<br>
As the initialization is not ambiguous, this can be written without<br>
``masked=True``::<br>
<br>
    &gt;&gt;&gt; np.array([1.0, 2.0, np.MASKED, 7.0])<br>
    array([1., 2., MASKED, 7.], masked=True)<br>
<br>
******<br>
Ufuncs<br>
******<br>
<br>
By default, NA values propagate::<br>
<br>
    &gt;&gt;&gt; na_arr = np.array([1.0, 2.0, np.NA, 7.0])<br>
    &gt;&gt;&gt; np.sum(na_arr)<br>
    NA(&#39;float64&#39;)<br>
<br>
unless the ``skipna`` flag is set::<br>
<br>
    &gt;&gt;&gt; np.sum(na_arr, skipna=True)<br>
    10.0<br>
<br>
By default, masking does not propagate::<br>
<br>
    &gt;&gt;&gt; masked_arr = np.array([1.0, 2.0, np.MASKED, 7.0])<br>
    &gt;&gt;&gt; np.sum(masked_arr)<br>
    10.0<br>
<br>
unless the ``propmsk`` flag is set::<br>
<br>
    &gt;&gt;&gt; np.sum(masked_arr, propmsk=True)<br>
    MASKED<br>
<br>
An array can be masked, and contain NA values::<br>
<br>
    &gt;&gt;&gt; both_arr = np.array([1.0, 2.0, np.MASKED, np.NA, 7.0])<br>
<br>
In the default case, the behavior is obvious::<br>
<br>
    &gt;&gt;&gt; np.sum(both_arr)<br>
    NA(&#39;float64&#39;)<br>
<br>
It&#39;s also obvious what to do with ``skipna=True``::<br>
<br>
    &gt;&gt;&gt; np.sum(both_arr, skipna=True)<br>
    10.0<br>
    &gt;&gt;&gt; np.sum(both_arr, skipna=True, propmsk=True)<br>
    MASKED<br>
<br>
To break the tie between NA and MSK, NAs propagate harder::<br>
<br>
    &gt;&gt;&gt; np.sum(both_arr, propmsk=True)<br>
    NA(&#39;float64&#39;)<br>
<br>
**********<br>
Assignment<br>
**********<br>
<br>
is obvious in the NA case::<br>
<br>
    &gt;&gt;&gt; arr = np.array([1.0, 2.0, 7.0])<br>
    &gt;&gt;&gt; arr[2] = np.NA<br>
    TypeError(&#39;dtype does not support NA&#39;)<br>
    &gt;&gt;&gt; na_arr = np.array([1.0, 2.0, 7.0], dtype=&#39;NA[f8]&#39;)<br>
    &gt;&gt;&gt; na_arr[2] = np.NA<br>
    &gt;&gt;&gt; na_arr<br>
    array([1., 2., NA], dtype=&#39;NA[&lt;f8]&#39;)<br>
<br>
Direct assignnent in the masked case is magic and confusing, and so happens only<br>
via the mask::<br>
<br>
    &gt;&gt;&gt; masked_array = np.array([1.0, 2.0, 7.0], masked=True)<br>
    &gt;&gt;&gt; masked_arr[2] = np.NA<br>
    TypeError(&#39;dtype does not support NA&#39;)<br>
    &gt;&gt;&gt; masked_arr[2] = np.MASKED<br>
    TypeError(&#39;float() argument must be a string or a number&#39;)<br>
    &gt;&gt;&gt; masked_arr.visible[2] = False<br>
    &gt;&gt;&gt; masked_arr<br>
    array([1., 2., MASKED], masked=True)<br>
<br>
See y&#39;all,<br>
<br></blockquote></div></div><div><br>I honestly don&#39;t see the problem here. The difference isn&#39;t between masked_values/missing_values, it is between masked arrays and masked views of unmasked arrays. I think the view concept is central to what is going on. It may not be what folks are used to, but it strikes me as a clarifying advance rather than a mixed up confusion. Admittedly, it depends on the numpy centric ability to have views, but views are a wonderful thing.<br>

<br></div></div></blockquote><div><br>OK, I can see a problem in that currently the only way to unmask a value is by assignment of a valid value to the underlying data array, that is the missing data idea. For masked data, it might be convenient to have something that only affected the mask instead of having to take another view of the unmasked data and reconstructing the mask with some modifications. So that could maybe be done with a &quot;soft&quot; np.CLEAR that only worked on views of unmasked arrays.<br>
<br>Chuck <br></div></div>