0

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 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

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.