I have a MaskedArray
a
of shape (L,M,N), and I want to transfer the unmasked elements to a normal array b
(with the same shape), such that along the last dimension, the first elements receive the non-masked values, and the remaining elements are zero. For example, in 2D:
a = [[--, 1, 2, --, 7, --, 5],
[3 , --, --, 2, --, --, --]]
# Transfer to:
b = [[1, 2, 7, 5, 0, 0, 0],
[3, 2, 0, 0, 0, 0, 0]]
The simplest way to do this would be over a for loop, e.g.,
for idx in np.ndindex(np.shape(a)[:-1]):
num = a[idx].count()
b[idx][:num] = a[idx].compressed()
# or perhaps,
# b[idx][:num] = a[idx][~a[idx].mask]
But this will be very slow for large arrays (and in fact, I have many different arrays with the same mask values, all of which I'd like to convert in the same way). Is there a fancy slicing way to do this?
Edit: Here is one way to construct the appropriate indexing tuple to assign value, but it seems ugly. Perhaps there's something better?
b = np.zeros(x.shape)
# Construct a list with a list for each dimension.
left = [[] for ii in range(a.ndim)]
# In each sub-list, construct the indices to `b` to store each value from `a`
for idx in np.ndindex(a.shape[:-1]):
num = a[idx].count()
# here `ii` is the dimension number, and jj the index in that dimension
for ii, jj in enumerate(idx):
left[ii] = left[ii] + num*[jj]
right[ii] = right[ii] + num*[jj]
# The last dimension is just consecutive numbers for as many values
left[-1] = left[-1] + list(range(num))
a[left] = b[~b.mask]