euler132
euler132

Reputation: 35

Python numpy.compress() to reduce a matrix

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

Upvotes: 0

Views: 1171

Answers (2)

hpaulj
hpaulj

Reputation: 231665

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

Upvotes: 1

Kevin
Kevin

Reputation: 3368

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

Upvotes: 1

Related Questions