0

If I have a (possibly multidimensional) Python list where each element is one of True, False, or ma.masked, what's the idiomatic way of turning this into a masked numpy array of bool?

Example:

>>> print(somefunc([[True, ma.masked], [False, True]]))
[[True --]
 [False True]]
Kyuuhachi
  • 651
  • 6
  • 15
  • given an example of `ma.masked`, and the expected result. – hpaulj Dec 11 '20 at 11:40
  • I did add a small example of the wanted input and output. – Kyuuhachi Dec 11 '20 at 13:07
  • I have not idea why you want this, or even where you get `ma.masked` from. Yes, `np.ma.masked` is an array object used by `np.ma` code, but I don't see the point in trying to make a list or array with it. – hpaulj Dec 11 '20 at 16:43
  • If you set `arr[x] = ma.masked`, that masks that slot. As for where I'm getting the values from, they're parsed from a file representing a 2D grid where one of the values matches the semantics of `np.masked` perfectly, so parsing it into a masked array directly instead of doing some inelegant multi-pass approach would be nice. – Kyuuhachi Dec 11 '20 at 21:33

1 Answers1

0

A masked array has to attributes, data and mask:

In [342]: arr = np.ma.masked_array([[True, False],[False,True]])
In [343]: arr
Out[343]: 
masked_array(
  data=[[ True, False],
        [False,  True]],
  mask=False,
  fill_value=True)

That starts without anything masked. Then as you suggest, assigning np.ma.masked to an element masks the slot:

In [344]: arr[0,1]=np.ma.masked
In [345]: arr
Out[345]: 
masked_array(
  data=[[True, --],
        [False, True]],
  mask=[[False,  True],
        [False, False]],
  fill_value=True)

Here the arr.mask has been changed from scalar False (applying to the whole array) to a boolean array of False, and then the selected item has been changed to True.

arr.data hasn't changed:

In [346]: arr.data[0,1]
Out[346]: False

Looks like this change to arr.mask occurs in data.__setitem__ at:

    if value is masked:
        # The mask wasn't set: create a full version.
        if _mask is nomask:
            _mask = self._mask = make_mask_none(self.shape, _dtype)
        # Now, set the mask to its value.
        if _dtype.names is not None:
            _mask[indx] = tuple([True] * len(_dtype.names))
        else:
            _mask[indx] = True
        return

It checks if the assignment values is this special constant, np.ma.masked, and it makes the full mask, and assigns True to an element.

hpaulj
  • 221,503
  • 14
  • 230
  • 353