0

I would like to reduce a NumPy matrix using the vector u and the numpy.compress() method, first going across the rows and then columns. Now my code looks like this:

n = 4 #number of rows/columns
square_matrix = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
u = np.array([1,0,1,0])

v = []

for i in range(n):
    v.append(np.compress(u,square_matrix[i]))

print(v)

I get the following output:

[array([1, 3]), array([5, 7]), array([ 9, 11]), array([13, 15])]

I have two questions:

  1. How can I now create a matrix from the output again.
  2. How could I repeat the same process for the columns. (My initial idea was to use a transpose of u, something like this:
for j in range((len(v_matrix[0])-1)):
    w.append(np.compress(u.transpose(),v_matrix[:][j]))
1
  • u is 1d, so transpose doesn't change anything. Looks a bit like you read just part of the np.compress docs, ignoring or no understanding the axis part. Commented Mar 30, 2021 at 16:15

2 Answers 2

1

compress like many numpy reduction functions takes an axis parameter:

In [166]: np.compress(u,square_matrix, axis=1)
Out[166]: 
array([[ 1,  3],
       [ 5,  7],
       [ 9, 11],
       [13, 15]])
In [167]: np.compress(u,square_matrix, axis=0)
Out[167]: 
array([[ 1,  2,  3,  4],
       [ 9, 10, 11, 12]])

Applying the compression sequentially:

In [168]: np.compress(u,np.compress(u,square_matrix, axis=0),axis=1)
Out[168]: 
array([[ 1,  3],
       [ 9, 11]])

I didn't realize np.compress existed, though from the source file it must have been there from the start. Boolean indexing is the same, and more common.

In [169]: bu = u.astype(bool)
In [170]: square_matrix[bu,:]
Out[170]: 
array([[ 1,  2,  3,  4],
       [ 9, 10, 11, 12]])
In [171]: square_matrix[:,bu]
Out[171]: 
array([[ 1,  3],
       [ 5,  7],
       [ 9, 11],
       [13, 15]])

Boolean indexing is equivalent to indexing with the nonzero result:

In [177]: np.nonzero(u)
Out[177]: (array([0, 2]),)
In [178]: idx = np.nonzero(u)[0]
In [179]: square_matrix[idx,:]
Out[179]: 
array([[ 1,  2,  3,  4],
       [ 9, 10, 11, 12]])

And that can be applied to both dimensions at once with:

In [180]: square_matrix[idx[:,None],idx]
Out[180]: 
array([[ 1,  3],
       [ 9, 11]])

Without the reshaping (making the first a column), we get the diagonal:

In [181]: square_matrix[idx,idx]
Out[181]: array([ 1, 11])

and using the ix_ utility:

In [185]: np.ix_(bu,bu)
Out[185]: 
(array([[0],
        [2]]),
 array([[0, 2]]))
In [186]: square_matrix[np.ix_(bu,bu)]
Out[186]: 
array([[ 1,  3],
       [ 9, 11]])
Sign up to request clarification or add additional context in comments.

Comments

1
  1. How can I now create a matrix from the output again.

You can do the operation in a vectorized manner, just specify the axis keyword for np.compress

np.compress(u, square_matrix, axis=1)

output:

array([[ 1,  3],
       [ 5,  7],
       [ 9, 11],
       [13, 15]])
  1. How could I repeat the same process for the columns. (My initial idea was to use a transpose of u)

Your suggestion is correct, but transpose the matrix instead of u. This will switch the columns with rows.

np.compress(u, square_matrix.T, axis=1)

output:

array([[ 1,  9],
       [ 2, 10],
       [ 3, 11],
       [ 4, 12]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.