Set values in row to zero before index value of row [NumPy or Tensorflow]

Viewed 521

I have an array A with shape (N,). I am taking N=5 for illustration:

A = np.array([0,1,1,0,1])

And I want to transform it to the following NxN matrix B. Solutions in both NumPy and Tensorflow are good but the latter is preferred.

B = np.array([[0,1,1,0,1],
              [0,1,1,0,1],
              [0,1,1,0,1],
              [0,0,0,0,1],
              [0,0,0,0,1]])

One solution can be comprised of following steps:

  1. Repeat array A N times
  2. Loop through each row i. Look for the index of the last zero until the i-th element of that row.
  3. Replace all elements preceding that index with zeros.

Another illustration with N=10:

D = np.array([0,1,1,1,0,0,1,1,0,0])
E = np.array([[0,1,1,1,0,0,1,1,0,0],
              [0,1,1,1,0,0,1,1,0,0],
              [0,1,1,1,0,0,1,1,0,0],
              [0,1,1,1,0,0,1,1,0,0],
              [0,0,0,0,0,0,1,1,0,0],
              [0,0,0,0,0,0,1,1,0,0],
              [0,0,0,0,0,0,1,1,0,0],
              [0,0,0,0,0,0,1,1,0,0],
              [0,0,0,0,0,0,0,0,0,0],
              [0,0,0,0,0,0,0,0,0,0]])
2 Answers
A = np.array([0,1,1,0,1])
N = A.shape[0]
column = (A > 0).reshape((N, 1))
mask = np.ones((N, N), dtype=np.bool)
mask = np.where(column, False, np.tril(mask, -1))
mask = np.cumsum(mask, axis=0)
B = np.where(mask, 0, np.tile(A, (N, 1)))
[[0 1 1 0 1]
 [0 1 1 0 1]
 [0 1 1 0 1]
 [0 0 0 0 1]
 [0 0 0 0 1]]

Explanation

  1. Compute lower triangular matrix
[[False False False False False]
 [ True False False False False]
 [ True  True False False False]
 [ True  True  True False False]
 [ True  True  True  True False]]
  1. Find ones in A and fill corresponding rows with False
[[False False False False False]
 [False False False False False]
 [False False False False False]
 [ True  True  True False False]
 [False False False False False]]
  1. Compute cumulative sum to set zeros to all rows below. This is a mask of all elements that should be zeroed out
[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [1 1 1 0 0]
 [1 1 1 0 0]]
  1. Repeat array A N times
[[0 1 1 0 1]
 [0 1 1 0 1]
 [0 1 1 0 1]
 [0 1 1 0 1]
 [0 1 1 0 1]]
  1. Mask its elements
[[0 1 1 0 1]
 [0 1 1 0 1]
 [0 1 1 0 1]
 [0 0 0 0 1]
 [0 0 0 0 1]]

@rafiko1 your explanation is still not clear to me. But try the following.

import numpy as np

nn = 5
A = np.array([0,1,1,0,1])
#A = np.array([0,1,1,1,0,0,1,1,0,0])

#  we create the matrix B and set required entries to zero
B = np.repeat(A.reshape(1,nn),nn,axis=0)

# test condition:
# test if the ith element in the ith row is zero
# this is accomplished using np.diag
boolarr = np.diag(B==0)
# this gives us the row index in B where the condition is true
idx_b_rows = np.where(boolarr == True)

# get indices of entries before diagonal
idx_lower_rows,idx_lower_cols = np.tril_indices(nn,k=-1)

# get the indices of the entries of idx_b_rows in idx_lower_rows
idx = np.where(np.in1d(idx_lower_rows,idx_b_rows))[0]

# set the entries before the diagonal to zero
B[idx_lower_rows[idx],idx_lower_cols[idx]] = 0

print(B)
 
Related