0

I have netcdf data that is masked. The data is in (time, latitude, longitude). I would like to make an array with the same size as the original data but with zeros when the data is masked and with ones where it is not masked. So fare I have tried to make this function:

def find_unmasked_values(data):
   empty = np.ones((len(data),len(data[0]),len(data[0,0])))
   for k in range(0,len(data[0,0]),1): # third coordinate
       for j in range(0,len(data[0]),1): # second coordinate
           for i in range(0,len(data),1): # first coordinate
               if ma.is_mask(data[i,j,k]) is True:
                   empty[i,j,k] = 0
   return(empty)

But this only returns an array with ones and no zeros eventhough there is masked values in the data. If you have suggestions on how to improve the code in efficiency I would also be very happy. Thanks,

Idalh
  • 31
  • 3

1 Answers1

1

Keep it simple! There is no need for all the manual loops, which will make your approach very slow for large data sets. A small example with some other data (where thl is a masked variable):

import netCDF4 as nc4

nc  = nc4.Dataset('bomex_qlcore_0000000.nc')
var = nc['default']['thl'][:]

mask_1 = var.mask  # masked=True, not masked=False
mask_2 = ~var.mask # masked=False, not masked=True

# What you need:
int_mask = mask_2.astype(int) # masked=0, not masked=1

p.s.: some other notes:

  • Instead of len(array), len(array[0]), et cetera, you can also directly get the shape of your array with array.shape, which returns a tupple with the array dimensions.
  • If you want to create a new array with the same dimensions as another one, just use empty = np.ones_like(data) (or np.zeros_like() is you want an array with zeros).
  • ma.is_mask() already returns a bool; no need to compare it with True.
  • Don't confuse is with ==: Is there a difference between "==" and "is"?
Bart
  • 9,825
  • 5
  • 47
  • 73