replace elements of a vector

36 次查看(过去 30 天)
Hi,
Is there a possibility to replace the zeros in A by the last non zero observation such as this case:
A=[1 0 2 2 8 0 0 0 3 5 7]
B=[1 1 2 2 8 8 8 8 3 5 7]
Thank you
  1 个评论
rithy vorn
rithy vorn 2016-11-12
hell0, could it be possible to do like this A=[1,2,3,4,5] to B=[5,4,3,2,1}

请先登录,再进行评论。

采纳的回答

Sean de Wolski
Sean de Wolski 2011-12-5
A=[1 0 2 2 8 0 0 0 3 5 7];
B = A; %copy
idx = logical(A); %locations to keep
Anr = A(idx); %locations to keep
idr = cumsum(idx); %where to replace?
idx = ~idx; %only do this once
B(idx) = Anr(idr(idx)) %replace
This will only run into issues if the first element is zero.
  1 个评论
Jan
Jan 2011-12-6
Let me repeat again, that this needs twice as long as Fangjun's loop.

请先登录,再进行评论。

更多回答(3 个)

Fangjun Jiang
Fangjun Jiang 2011-12-6
What's wrong with using a simple, old, straightforward for-loop? Jan will help me prove that it's faster than other approaches.
A=[1 0 2 2 8 0 0 0 3 5 7];
if A(1)==0
error('invalid data');
end
for k=2:length(A)
if A(k)==0;
A(k)=A(k-1);
end
end
Or an even better solution
A=[1 0 2 2 8 0 0 0 3 5 7];
if A(1)==0
error('invalid data');
end
Ind=find(A==0);
for k=Ind
A(k)=A(k-1);
end
  3 个评论
Tiina
Tiina 2011-12-6
Thank you works fine.
Fangjun Jiang
Fangjun Jiang 2011-12-6
@Jan, Thank you for backing me up.
I can think of another improvement. See update.

请先登录,再进行评论。


Sven
Sven 2011-12-5
Hi Tiina, try this. It uses find and arrayfun to replace the zero-values of A with the nearest preceding non-zero value:
zeroInds = find(A==0);
repVals = arrayfun(@(ind)A(find(A(1:ind),1,'last')), zeroInds);
A(zeroInds) = repVals;
Note that if the first element of A is a zero, then the question itself hits a problem, but the above works fine in other cases.
  5 个评论
Jan
Jan 2011-12-6
Rule 3. All the small dots and crumbs, quotes and the tails of curly braces looks like flyspecks when you observe the monitor from a certain distance.
Rule 4. If you are in doubt, they are flyspecks.
Sven
Sven 2011-12-6
Rule 5. If you're in a hurry and just copy Walter's comment code, HE WILL make a typo :)
(now *that* was unexpected)

请先登录,再进行评论。


Jan
Jan 2011-12-6
A = rand(1, 1e6);
A(rand(size(A)) < 0.1) = 0; % 10% zeros
tic; for i = 1:20; B = F1(A); end; toc
Some timings (Matlab 2009b/64, Win7, Core2Duo):
function A = F1(A) % ======================================
n = A~=0;
A(~n) = cell2mat(arrayfun(@(x,y)A(x)*ones(1,y-x),...
strfind(n,[1, 0]),strfind([n, 1],[0, 1]),'un',0))
20.528223 sec
function A = F2(A) % ======================================
nonZero = (A ~= 0);
B = A(nonZero);
A = B(cumsum(nonZero));
1.198049 sec
function A = F3(A) % ======================================
idx = logical(A); %locations to keep
Anr = A(idx); %locations to keep
idr = cumsum(idx); %where to replace?
idx = ~idx; %only do this once
A(idx) = Anr(idr(idx)); %replace
1.151062 sec
function A=F4(A) % ======================================
if A(1)==0
error('invalid data');
end
for k=2:length(A)
if A(k)==0
A(k)=A(k-1);
end
end
0.615451 sec
#include "mex.h" // ====================================
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *A;
mwSize i, n;
//
n = mxGetNumberOfElements(prhs[0]);
plhs[0] = mxDuplicateArray(prhs[0]);
A = mxGetPr(plhs[0]);
//
if (A[0] == 0.0) {
mexErrMsgIdAndTxt("JSimon:FillZeros:BadData", "Input starts with 0.");
}
for (i = 0; i < n; i++) {
if (A[i] == 0.0) {
A[i] = A[i - 1];
}
}
return;
}
0.210786 sec
The loop ist the fastest Matlab method, because it does not need temporary memory. Another hint to follow the KISS rule: Keep it simply stupid.
But still C is faster in loops.

类别

Help CenterFile Exchange 中查找有关 Parallel for-Loops (parfor) 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by