Replace zero in a matrix with value in previous row

Hi,
Can you please help me on how can I replace all zeroes in a matrix with the value in previous row?
e.g. if value in row 3 column 4 is 0, it should pick value in row 2 column 4.
I can do it using a for loop but I dont want to use that.
Thanks.

 Akzeptierte Antwort

Azzi Abdelmalek
Azzi Abdelmalek am 1 Feb. 2014
Bearbeitet: Azzi Abdelmalek am 1 Feb. 2014
A=[1 2 3 4;4 5 0 0;1 0 0 1 ;0 1 1 1]
while any(A(:)==0)
ii1=A==0;
ii2=circshift(ii1,[-1 0]);
A(ii1)=A(ii2);
end

4 Kommentare

Mohit
Mohit am 1 Feb. 2014
Thanks
Mido
Mido am 3 Nov. 2016
What should I do if I want to apply this process on a specific column. For example the third one?
@Mido: Please open a new thread for a new question.
match = (A(:, 3)==0);
A(match, 3) = A(match, 2);
Pardis
Pardis am 16 Mär. 2020
Very helpful, thank you Azzi!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (5)

Shivaputra Narke
Shivaputra Narke am 1 Feb. 2014

1 Stimme

Now answer to your comment...
while(all(a(:))) a(find(a==0))=a(find(a==0)-1) end

3 Kommentare

Mohit
Mohit am 1 Feb. 2014
Thanks
That expression doesn't work as written in a single line. Without a ; after the assignment, it gets an error 'Error: Illegal use of reserved keyword "end".` If I add the ; however, it doesn't error but it still doesn't work. I'm not sure why, because logically it seems like it should, but I just get the original a out when I run it.
DGM
DGM am 3 Dez. 2022
Bearbeitet: DGM am 3 Dez. 2022
The loop is never entered at all. You could make some modifications.
a = [0 5 9 13; 2 6 0 0; 3 0 0 15; 0 8 12 16]
a = 4×4
0 5 9 13 2 6 0 0 3 0 0 15 0 8 12 16
na = numel(a);
while ~all(a(:)) % loop runs until there are no zeros
idx = find(a==0);
a(idx) = a(mod(idx-2,na)+1);
end
a
a = 4×4
16 5 9 13 2 6 9 13 3 6 9 15 3 8 12 16
The redundant find() can be removed. Since this is based on decrementing the linear indices, this will fill zeros at the top of a column with content from the bottom of the prior column. Using mod() allows the wrapping behavior to extend across the ends of the array. Note that a(1,1) is filled from a(16,16).
Whether this wrapping behavior is intended or acceptable is a matter for the reader to decide.

Melden Sie sich an, um zu kommentieren.

Andrei Bobrov
Andrei Bobrov am 1 Feb. 2014
l = A == 0;
ii = bsxfun(@plus,size(A,1)*(0:size(A,2)-1),cumsum(~l));
out = A;
out(l) = A(ii(l));
Shivaputra Narke
Shivaputra Narke am 1 Feb. 2014

0 Stimmen

May be this code can help...
% where a is your matrix a(find(a==0))=a(find(a==0)-1)

2 Kommentare

Amit
Amit am 1 Feb. 2014
This will not work in many scenarios.
Mohit
Mohit am 1 Feb. 2014
Thanks a lot, it works!
What should I do in case I want to put another condition that if cell value above zero cell is also zero then go one cell up.
e.g. if value in row 6 column 4 is 0, it should pick value in row 5 column 4. If value in row 5 column 4 is also zero then it should pick value in row 4 column 4 and so on.

Melden Sie sich an, um zu kommentieren.

Amit
Amit am 1 Feb. 2014
Lets say your matrix is A
[m,n] = size(A);
An = A';
valx = find(~An); % This will give you zeros elements linear index
valx = valx(valx-n > 0);
An(valx) = An(valx-n);
A = An';
Paul
Paul am 1 Feb. 2014
idx=find(A==0)
A(idx)=A(idx-1)

3 Kommentare

This solution is similar to what Shivaputra posted. This solution will also fail. find(A==0) give linear indexing. Imaging that you have first row with some values 0. This approach will fill up those first row values with a value too.
Try these solution for a matrix like:
A = [1 0 0;2 1 0;2 3 1]
Thank you Amit. My solution wont work on such scenarios.
Mohit
Mohit am 1 Feb. 2014
Thanks

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrices and Arrays finden Sie in Hilfe-Center und File Exchange

Tags

Gefragt:

am 1 Feb. 2014

Bearbeitet:

DGM
am 3 Dez. 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by