Home > Software design >  Creating submatrix in python
Creating submatrix in python

Time:09-28

Given a matrix S and a binary matrix W, I want to create a submatrix of S corresponding to the non zero coordinates of W.

For example:

S = [[1,1],[1,2],[1,3],[1,4],[1,5]]
W = [[1,0,0],[1,1,0],[1,1,1],[0,1,1],[0,0,1]]

I want to get matrices

S_1 = [[1,1],[1,2],[1,3]]
S_2 = [[1,2],[1,3],[1,4]]
S_3 = [[1,3],[1,4],[1,5]]

I couldn't figure out a slick way to do this in python. The best I could do for each S_i is

S_1 = S[0,:]

for i in range(np.shape(W)[0]):
    if W[i, 0] == 1:
        S_1 = np.vstack((S_1, S[i, :]))

but if i want to change the dimensions of the problem and have, say, 100 S_i's, writing a for loop for each one seems a bit ugly. (Side note: S_1 should be initialized to some empty 2d array but I couldn't get that to work, so initialized it to S[0,:] as a placeholder).

EDIT: To clarify what I mean:

I have a matrix S

1 1
1 2
1 3 
1 4
1 5

and I have a binary matrix

1 0 0
1 1 0
1 1 1
0 1 1
0 0 1

Given the first column of the binary matrix W

1
1
1
0
0

The 1's are in the first, second, and third positions. So I want to create a corresponding submatrix of S with just the first, second and third positions of every column, so S_1 (corresponding to the 1st column of W) is

1 1
1 2
1 3

Similarly, if we look at the third column of W

0
0
1
1
1

The 1's are in the last three coordinates and so I want a submatrix of S with just the last three coordinates of every column, called S_3

1 3
1 4
1 5

So given any ith column of the binary matrix, I'm looking to generate a submatrix S_i where the columns of S_i contain the columns of S, but only the entries corresponding to the positions of the 1's in the ith column of the binary matrix.

CodePudding user response:

It probably is more useful to work with the transpose of W rather than W itself, both for human-readability and to facilitate writing the code. This means that the entries that affect each S_i are grouped together in one of the inner parentheses of W, i.e. in a row of W rather than a column as you have it now.

Then, S_i = np.array[S[j,:] for j in np.shape(S)[0] if W_T[i,j] == 1], where W_T is the transpose of W. If you need/want to stick with W as is, you need to reverse the indices i and j.

As for the outer loop, you could try to nest this in another similar comprehension without an if statement--however this might be awkward since you aren't actually building one output matrix (the S_i can easily be different dimensions, unless you're somehow guaranteed to have the same number of 1s in every column of W). This in fact raises the question of what you want--a list of these arrays S_i? Otherwise if they are separate variables as you have it written, there's no good way to refer to them in a generalizable way as they don't have indices.

CodePudding user response:

Numpy can do this directly.

import numpy as np
S = np.array([[1,1],[1,2],[1,3],[1,4],[1,5]])
W = np.array([[1,0,0],[1,1,0],[1,1,1],[0,1,1],[0,0,1]])

for row in range(W.shape[1]):
    print(S[W[:,row]==1])

Output:

[[1 1]
 [1 2]
 [1 3]]
[[1 2]
 [1 3]
 [1 4]]
[[1 3]
 [1 4]
 [1 5]]
  • Related