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일

0 개 추천

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일

3 개 추천

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

Jan
Jan 2011년 12월 6일
+1: Fastest Matlab method. You find the measurements in my answer.
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일

1 개 추천

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

Walter Roberson
Walter Roberson 2011년 12월 5일
You seem to have missed the closing bracket on the arrayfun, and you missed the parameter indicating the array that is to be processed. I suspect the line should be
repVals = arrayfun(@(ind)A(find(A(1:ind),1,'last'), zeroInds);
Sven
Sven 2011년 12월 5일
Yep, thanks Walter... the laws of MATLAB Answers:
Rule 1. IF you type an answer without running the code in MATLAB, you WILL make a typo.
Rule 2. IF you start your answer in the browser, remember Rule 1, then check your answer in MATLAB, you WILL forget to copy it back into the browser :)
Sean de Wolski
Sean de Wolski 2011년 12월 5일
Sven, that should be in the tutorial!
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일

1 개 추천

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.

카테고리

도움말 센터File Exchange에서 Parallel for-Loops (parfor)에 대해 자세히 알아보기

태그

질문:

2011년 12월 5일

댓글:

2016년 11월 12일

Community Treasure Hunt

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

Start Hunting!

Translated by