0

I have arrays that are simple numpy.ndarrays while other times the same variable may be a masked array. I'd like to figure out the most effective way to check if there are data in the array and that ALL are not masked

I've got the below to illustrate:

data0 = np.ma.array([3,3,3,3,3], mask=[True, True, False, True, True])
data1 = np.ma.array([3,3,3,3,3], mask=[True, True, True, True, True])
data2 = np.array([3,3,3,3,3])
for dataNum, data in enumerate([data0, data1, data2]):
    if (isinstance(data, np.ma.masked_array) and not data.mask.all()) or (isinstance(data,np.ndarray)):
         print('if statement passed data{}'.format(dataNum))

but this allows for all 3 to pass. I assume because a masked_array is considered an ndarray

if statement passed data0 if statement passed data1 if statement passed data2

i'd like for data0 and data2 to pass so I can operate on the data. Ideally it's something simple too :)

SBFRF
  • 167
  • 2
  • 16

3 Answers3

2

Here's a simple solution that avoids the multiple cases by first ensuring that the data is masked and then testing the mask (which defaults to False):

not np.ma.array(data).mask.all()

So for your specific example:

for dataNum, data in enumerate([data0, data1, data2]):
    if not np.ma.array(data).mask.all():
        print('if statement passed data{}'.format(dataNum))

gives the results you wanted.

Edit: for reduced overhead you can use copy=False:

not np.ma.array(data, copy=False).mask.all()
Jsl
  • 842
  • 1
  • 5
  • 10
1

turns out the np.ma.isMaskedArray solves this problem:

for dataNum, data in enumerate([data0, data1, data2]):
    if (np.ma.isMaskedArray(data) and not data.mask.all()) or not np.ma.isMaskedArray (data):
         print('if statement passed data{}'.format(dataNum))

if statement passed data0 if statement passed data2

SBFRF
  • 167
  • 2
  • 16
0

There are two problems:

  1. for all arrays you have isinstance(data,np.ndarray) to be True.
  2. not data.mask.all() looks a typo to me.

This should fix

for dataNum, data in enumerate([data0, data1, data2]):
    if ((isinstance(data, np.ma.masked_array) and  data.mask.all()) or 
        not (isinstance(data, np.ma.masked_array))):
         print('if statement passed data{}'.format(dataNum))
rpanai
  • 12,515
  • 2
  • 42
  • 64
  • 1
    this passes data1 and data 2 not data0 and data2 – SBFRF Nov 14 '19 at 22:58
  • It was not clear from first version of question where data numbering was shifted. That's why I wrote point 2. As long as you add a `not` in front of `data.mask.all()` you have the wished solution. – rpanai Nov 15 '19 at 11:20
  • 1
    agreed, that was a typo on initial question submission, based on modifications before initial submission. – SBFRF Nov 15 '19 at 15:21