1

I have a numpy array in python called my_values of size 5x5 and a numpy vector which contains boolean values with size 1x90 (5 False, 85 True) naned cols_indexes. I want to expand my initial array my_values with zeros in the positions indexes of the cols_indexes that are equal to False. Thus in the end my transformed matrix my_values should be of size 5x90 (with 85 new columns filled with zero). A simple example that uses an array instead of a vector of Boolean's is:

def insert_one_per_row(arr, mask, putval):

   mask_ext = np.column_stack((mask, np.zeros((len(mask), 1), dtype=bool)))
   out = np.empty(mask_ext.shape, dtype=arr.dtype)
   out[~mask_ext] = arr.ravel()
   out[mask_ext] = putval
   return out

y = np.arange(25).reshape(5, 5)
x = np.array([[False,  True,  False, False, False],
          [False,  True,  False, False, False],
          [False,  True,  False, False, False],
          [False,  True,  False, False, False],
          [False,  True,  False, False, False]], dtype=bool)

arr = insert_one_per_row(y, x, putval=0)

This example works with an array of Boolean's. However in my case x is a vector instead of an array. x contains True for a new column in the position that I need to add and False for an existing one in the position of the final array. How can I insert the new columns using the vector x instead of the matrix x?

Jose Ramon
  • 5,572
  • 25
  • 76
  • 152
  • 2
    See https://stackoverflow.com/questions/5064822/how-to-add-items-into-a-numpy-array/5068182#5068182 Conclusion is that there are methods around, but it's better to start with an array as large as you're going to need and fill in values as needed. – Seth Rothschild Apr 10 '18 at 14:19
  • In my case is necessary to do the opposite since I need to process the matrix without the zeros. – Jose Ramon Apr 10 '18 at 14:22
  • That happens. Do the stack functions like https://docs.scipy.org/doc/numpy/reference/generated/numpy.stack.html#numpy.stack that are there not work for your needs? – Seth Rothschild Apr 10 '18 at 14:25
  • You might have a mistake in the question? You wrote you want to have zeros in "positions indexes of the cols_indexes that are equal to False", but there are 5 Falses, not 85. – Shir Apr 10 '18 at 14:33
  • Yes true I meant the opposite. I edited the question. – Jose Ramon Apr 10 '18 at 14:37
  • How about using `np.tile(x,(5,1))` to create the matrix mask from a vector `x`? – Shir Apr 10 '18 at 14:47
  • The issue is that if that matrix is bigger than the size of my my_values it does not work – Jose Ramon Apr 10 '18 at 15:24
  • In my example I can add only one column. If two columns are true then it does not work. – Jose Ramon Apr 10 '18 at 15:26

1 Answers1

1

Your inputs - adjusted to work:

In [73]: y = np.arange(1,21).reshape(5, 4)
    ...: x = np.array([[False,  True,  False, False, False],
    ...:           [False,  True,  False, False, False],
    ...:           [False,  True,  False, False, False],
    ...:           [False,  True,  False, False, False],
    ...:           [False,  True,  False, False, False]], dtype=bool)
    ...:           

The whole array masking, roughly what your function does

In [74]: res = np.full(x.shape, 0)    # assign the putval on creation
In [75]: res[~x] = y.ravel()
In [76]: res
Out[76]: 
array([[ 1,  0,  2,  3,  4],
       [ 5,  0,  6,  7,  8],
       [ 9,  0, 10, 11, 12],
       [13,  0, 14, 15, 16],
       [17,  0, 18, 19, 20]])

We can use where to get the column indices from a 1d mask, here a row of x:

In [77]: res[:, np.where(~x[0,:])[0]]
Out[77]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16],
       [17, 18, 19, 20]])

assignment - but don't use ravel since the RHS is (4,5). This indexing doesn't flatten array like the full boolean mask:

In [80]: res[:, np.where(~x[0,:])[0]] = 2*y
In [81]: res
Out[81]: 
array([[ 2,  0,  4,  6,  8],
       [10,  0, 12, 14, 16],
       [18,  0, 20, 22, 24],
       [26,  0, 28, 30, 32],
       [34,  0, 36, 38, 40]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353