3

I'm using the np.broadcast_to function to get a view on a reshaped array just like the example:

>>> x = np.array([1, 2, 3])
>>> np.broadcast_to(x, (3, 3))
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

Passing a masked array to this function loses me the mask though:

>>> y = np.ma.array([1, 2, 3], mask=[False, True, False])
>>> np.broadcast_to(y, (3, 3))
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

How do I get the following view?

array([[1, --, 3],
       [1, --, 3],
       [1, --, 3]])
Duncan WP
  • 830
  • 5
  • 19
  • `--` is not a valid Numpy nor Python identifier. What `--` is supposed to be? None? – Mazdak Nov 23 '17 at 10:38
  • 1
    @Kasramvd `--` is used in the display of the masked items for masked arrays. – Moses Koledoye Nov 23 '17 at 10:40
  • I'll have expected passing `subok=True` in `np.broadcast_to` to return the result you want, but unfortunately, it doesn't. The mask is not broadcasted. – Moses Koledoye Nov 23 '17 at 10:45
  • As a general rule numpy functions don't 'know-about' masked arrays. They tend to just use the `data` part. `np.ma` functions work, as do ones that delegate the task to a masked method. – hpaulj Nov 23 '17 at 11:23

3 Answers3

4

Apparently, you can pass a subok parameter to np.broadcast_to to retain the type of the passed array and not use the base array type, but this only broadcasts the data of the masked array, not the mask.

You should probably manually broadcast the mask afterwards:

>>> y = np.ma.array([1, 2, 3], mask=[False, True, False])
>>> z = np.broadcast_to(y, (3, 3), subok=True)
>>> z.mask
False
>>> z.mask = np.broadcast_to(y.mask, z.shape)
>>> z
masked_array(data =
 [[1 -- 3]
 [1 -- 3]
 [1 -- 3]],
             mask =
 [[False  True False]
 [False  True False]
 [False  True False]],
       fill_value = 999999)
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
1

I think this is what you want. Mask the array after broadcast, So that you get the desired masked array.

y = np.ma.array([1, 2, 3])
z = np.broadcast_to(y, (3, 3))
x = np.ma.array(z, mask=np.broadcast_to([False,True,False], (3, 3)))
x
masked_array(data =
 [[1 -- 3]
 [1 -- 3]
 [1 -- 3]],
             mask =
 [[False  True False]
 [False  True False]
 [False  True False]],
       fill_value = 999999)

Check if this worked for your case. If you want the masked array values without '--'

x.compressed()
array([1, 3, 1, 3, 1, 3])

For more information go through Masked array documentation

Space Impact
  • 13,085
  • 23
  • 48
  • Yes, that should work. I can pass `y.mask` rather than `[0,1,0]` to make it more general. The `copy` argument defaults to `False` in the `np.ma.array' function too so it should return a view. Thanks – Duncan WP Nov 23 '17 at 10:52
0

Building on @Sandeep Kadapa's helpful result (I lack the reputation to comment), I built a function that can be used to find and replace calls of numpy.broadcast_to:

import numpy as np

def ma_broadcast_to(maskedarray,tup):
        initial_mask=np.ma.getmask(maskedarray)
        broadcasted_mask=np.broadcast_to(initial_mask,tup)
        broadcasted_array=np.broadcast_to(maskedarray,tup)
        return np.ma.array(broadcasted_array, mask=broadcasted_mask)

and applied to the OP

y = np.ma.array([1, 2, 3], mask=[False, True, False])
ma_broadcast_to(y,(3,3))

returns

masked_array(
  data=[[1, --, 3],
        [1, --, 3],
        [1, --, 3]],
  mask=[[False,  True, False],
        [False,  True, False],
        [False,  True, False]],
  fill_value=999999)
Chappy Hickens
  • 397
  • 2
  • 5