Replace all zeros in vector by previous non-zero value
I think it is possible, let's start with the basics, you want to capture where number is greater than 0:
a = [ 1 0 2 0 7 7 7 0 5 0 0 0 9 ] %//Load in Vector
pada = [a,888]; %//Pad A with a random number at the end to help in case the vector ends with a 0
b = pada(find(pada >0)); %//Find where number if bigger than 0
bb = b(:,1:end-1); %//numbers that are bigger than 0
c = find (pada==0); %//Index where numbers are 0
d = find(pada>0); %//Index where numbers are greater than 0
length = d(2:end) - (d(1:end-1)); %//calculate number of repeats needed for each 0 trailing gap.
%//R = [cell2mat(arrayfun(@(x,nx) repmat(x,1,nx), bb, length,'uniformoutput',0))]; %//Repeat the value
----------EDIT---------
%// Accumarray and cumsum method, although not as nice as Dan's 1 liner
t = accumarray(cumsum([1,length])',1);
R = bb(cumsum(t(1:end-1)));
NOTE: I used arrayfun
, but you can use accumarray
as well.I think this demonstrates that it is possible to do this in parallel?
R =
Columns 1 through 10
1 1 2 2 7 7 7 7 5 5
Columns 11 through 13
5 5 9
TESTs:
a = [ 1 0 2 0 7 7 7 0 5 0 0 0 9 0 0 0 ]
R =
Columns 1 through 10
1 1 2 2 7 7 7 7 5 5
Columns 11 through 16
5 5 9 9 9 9
PERFORMANCE:
a = repmat([ 1 0 2 0 7 7 7 0 5 0 0 0 9 ] ,1,10000); %//Double of 130,000
Arrayfun Method : Elapsed time is 6.840973 seconds.
AccumArray Method : Elapsed time is 2.097432 seconds.
The following simple approach does what you want, and is probably very fast:
in = [1 0 2 0 7 7 7 0 5 0 0 0 9];
t = cumsum(in~=0);
u = nonzeros(in);
out = u(t).';
I think is a vectorized solution. Works on your example:
V = [1 0 2 0 7 7 7 0 5 0 0 0 9]
%// This is where the numbers you will repeat lie. You have to cast to a double otherwise later when you try assign numbers to it it caps them at logical 1s
d = double(diff([0,V])>0)
%// find(diff([0,~V])==-1) - find(diff([0,~V])==1) is the length of each zero cluster
d(find(d(2:end))+1) = find(diff([0,~V])==-1) - find(diff([0,~V])==1)
%// ~~V is the same as V ~= 0
V(cumsum(~~V+d)-1)