フィルターのクリア

Loop step size issue

7 ビュー (過去 30 日間)
Swisslog
Swisslog 2013 年 1 月 22 日
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 日
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 日
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 日
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))];

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by