Loop step size issue

Hoping there is a very simple solution to this but being new to matlab can't quite see where I'm going wrong:
for i = 10:5:100;
sums = conv(S, ones(1, i), 'valid');
Output(i) = nnz(sums>2 & sums<3);
end
where S is a column vector of values The code searches for instances where the sum of a block of data contained in window (i) is either >2 or <3 and counts them.
I was expecting the Output to return 19 values based on the step size of 5. Instead I get 100 values. I only want to return the counts for window sizes equal to i. Any thoughts would be much appreciated.

댓글 수: 1

Image Analyst
Image Analyst 2013년 1월 22일
That's because conv() moves the window over 1 element at a time. If you want to move in "jumps" of the window size, you need to use blockproc().

댓글을 달려면 로그인하십시오.

답변 (3개)

Walter Roberson
Walter Roberson 2013년 1월 22일
편집: Walter Roberson 2013년 1월 22일

0 개 추천

ivals = 10:5:100;
ni = length(ivals);
for K = 1 : ni
i = ivals(K);
sums = conv(S, ones(1, i), 'valid');
Output(K) = nnz(sums>2 & sums<3);
end

댓글 수: 2

Swisslog
Swisslog 2013년 1월 22일
Thanks, this works fine I think. Still slow, I don't suppose there is any way to get this vectorised is there?
Matt J
Matt J 2013년 1월 22일
편집: Matt J 2013년 1월 22일
I don't think there's a way to vectorize fully, but if the S(i) are all non-negative, you should be sure to bail out of the loop once any(sums<3)==0. Enlarging the window from that point on will not change the result.
ivals = 10:5:100;
ni = length(ivals);
Output=zeros(ni,1);
flag=false;
for K = 1 : ni
i = ivals(K);
sums = conv(S, ones(1, i), 'valid');
Usums=sums<3;
if ~any(Usums)
break
end
Lsums=sums>2;
Output(K) = sum(Usums&Lsums);
end

댓글을 달려면 로그인하십시오.

Thorsten
Thorsten 2013년 1월 22일
편집: Thorsten 2013년 1월 22일

0 개 추천

Walter's solution is more efficient. If you want to do it quick
Output = nan(1, 100);
% your code here
Output = Output(Output(~isnan(Output));
Thorsten
Thorsten 2013년 1월 22일

0 개 추천

This runs about 4 times faster on my machine:
cS = cumsum(S);
for K = 1 : ni
sums = cS(ivals(K):end) - [0 cS(1:end-ivals(K))];
Output(K) = nnz(sums>2 & sums<3);
end

댓글 수: 2

Matt J
Matt J 2013년 1월 22일
편집: Matt J 2013년 1월 22일
Not on mine.
S=rand(1,1e6);
ivals = 10:5:100;
ni = length(ivals);
Output=zeros(ni,1);
tic
for K = 1 : ni
i = ivals(K);
sums = conv(S, ones(1, i), 'valid');
Output(K) = nnz(sums>2 & sums<3);
end
toc
%Elapsed time is 0.313358 seconds.
tic;
cS = cumsum(S);
for K = 1 : ni
sums = cS(ivals(K):end) - [0 cS(1:end-ivals(K))];
Output(K) = sum(sums>2 & sums<3);
end
toc;
%Elapsed time is 0.437812 seconds.
Matt J
Matt J 2013년 1월 22일
I really do think the CUMSUM approach should be the better one, though. A MEX is probably needed to avoid repeated memory allocation operations in
sums = cS(ivals(K):end) - [0 cS(1:end-ivals(K))];

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Timing and presenting 2D and 3D stimuli에 대해 자세히 알아보기

질문:

2013년 1월 22일

Community Treasure Hunt

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

Start Hunting!

Translated by