0
votes

I'm a new programmer, working in MATLAB, and I am hoping to substitute some values in one of my matrices with information from another matrix.

So, for example, supposing I have one matrix [A]:

A = [0  0  0  0  0  
    .5  0 .2 .8  0
     1 .3  1 .1 .1
     1  1 .4  1  1
     1  1  1  1  1] 

And another matrix B:

B = [.4 .3 .2 .1 .2] 

I would like to replace the first nonzero value in A with the one in the same column in matrix B such that:

A_new = [0  0  0  0  0  
        .4  0 .2 .1  0
         1 .3  1 .1 .2
         1  1 .4  1  1
         1  1  1  1  1] 

There are some values between 0 and 1 that I want to keep untouched which precludes just changing everything between 0 and 1 (exclusive). I'm sure the solution will involve an if statement and possibly a for loop, but I'm not sure how to set it up. Any advice is appreciated!

2

2 Answers

1
votes

Try this:

[~, row] = max(A~=0);
A(row + (0:size(A,1):numel(A)-1)) = B

How it works:

The first line produces a vector row containing the index of the first nonzero row in each column. This use of max is a "column-wise find" of sorts. Namely, max works down each column and tells you the row index of the maximum value in that column. Since each column only contains 0 or 1, there may be several maximizing (1) values; max gives the (index of) the first one.

In the second line that vector is transformed into a linear index to replace those elements of A.

1
votes

Another way, though probably inefficient, is to use find and search for row and column locations that are non-zero. Once you find this, because MATLAB searches for non-zero entries column-wise, you can apply diff to the column indices and find transitions. The elements on the right-hand of the transition denote the first non-zero value for each column. Once you find these locations, get the corresponding row locations for these entries, create a new matrix A_new that is a copy of A, then change the corresponding entries to B. You'll need to use sub2ind for the assignment.

Something like this:

%// Define matrix
A = [0  0  0  0  0  
    .5  0 .2 .8  0
     1 .3  1 .1 .1
     1  1 .4  1  1
     1  1  1  1  1];

%// Find non-zero entries
[row,col] = find(A);

%// Figure out the column locations that are the first non-zero for each column
ind = diff([Inf; col]) ~= 0;

%// Create a new matrix that is a copy of the old one
A_new = A;

%// Create the B vector
B = [.4 .3 .2 .1 .2];

%// Do the assignment
A_new(sub2ind(size(A), row(ind), (1:size(A,2)).')) = B;

Doing sub2ind is perhaps inefficient because there is a lot error checking done and that can slow things down. You can compute the linear indices manually by:

columns = size(A,2);
A_new((0:columns-1).'*columns + row(ind)) = B;

Running the above code, we get:

>> A

A =

         0         0         0         0         0
    0.5000         0    0.2000    0.8000         0
    1.0000    0.3000    1.0000    0.1000    0.1000
    1.0000    1.0000    0.4000    1.0000    1.0000
    1.0000    1.0000    1.0000    1.0000    1.0000

>> A_new

A_new =

         0         0         0         0         0
    0.4000         0    0.2000    0.1000         0
    1.0000    0.3000    1.0000    0.1000    0.2000
    1.0000    1.0000    0.4000    1.0000    1.0000
    1.0000    1.0000    1.0000    1.0000    1.0000