Jose Ramon
Jose Ramon

Reputation: 5444

Insert new columns into numpy array

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?

Upvotes: 1

Views: 121

Answers (1)

hpaulj
hpaulj

Reputation: 231335

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]])

Upvotes: 1

Related Questions