Reputation: 35
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!
Upvotes: 0
Views: 745
Reputation: 104464
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
Upvotes: 1
Reputation: 112659
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
.
Upvotes: 1