Vectorize for-loop that changes overlapping parts of an array
1 回表示 (過去 30 日間)
古いコメントを表示
Hi everyone,
I have problem speeding up my code. I have a very large (20-40m datapoints) logical array and at every position where it reads "1", the next N datapoints should be set to "1" a well.
I have the following code that is quite slow since it has a for loop:
N=5000-1;
logarray; %logical array of size 40000000x1
inx=find(logarray); %inx can be quite large as well, 1-5m points
for ii=1:length(inx)
logarray(inx(ii):(inx(ii)+N))=1;
end
This code works, but is very slow (more than 10 secs). I tried something like
logarray(find(inx):(find(inx)+100))=1;
but this did not work. I was wondering whether vectorisation would be a solution here? Mind that overlapping parts of the logical array are changed by the loop.
Does anyone have a good suggestion?
Thanks, Maximilian
0 件のコメント
採用された回答
Jos (10584)
2016 年 4 月 20 日
編集済み: Jos (10584)
2016 年 4 月 20 日
Easy when using convolution:
logarray = logical([0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1])
N = 2 ;
out = conv2(double(logarray(:)), ones(N+1,1)) ;
out = out(1:numel(logarray))>0 ;
out = reshape(out,size(logarray)) ;
disp([logarray(:) ; out(:)]) ;
2 件のコメント
その他の回答 (1 件)
Roger Stafford
2016 年 4 月 20 日
編集済み: Roger Stafford
2016 年 4 月 20 日
It isn't perhaps that you have a for-loop that is slowing you down so much as that your loop is repeating the writing of ones so much in overlapping intervals. You might try the following which first combines overlapping intervals before doing the writing of ones.
N=5000-1;
f1 = find(logarray);
f2 = min(f1+N,length(logarray));
f3 = zeros(size(f1));
f4 = zeros(size(f2));
ie = 1;
f3(ie) = f1(ie);
f4(ie) = f2(ie);
for ib = 1:size(f1,1)-1
if f1(ib+1) > f4(ie)+1
ie = ie+1;
f3(ie) = f1(ib+1);
end
f4(ie) = f2(ib+1);
end
f3 = f3(1:ie); % The intervals defined by f3 and f4 don't overlap
f4 = f4(1:ie);
for ib = 1:ie
logarray(f3(ib):f4(ib)) = 1;
end
1 件のコメント
Roger Stafford
2016 年 4 月 20 日
I thought of another way you could try which uses 'accumarray'. Assume 'logarray' is a column vector.
N = 1000;
f = find(logarray);
t = ones(size(f));
logarray = min(cumsum(accumarray([f;f+N+1],[t;-t],...
[length(logarray)+N+1,1])),1);
logarray(end) = [];
参考
カテゴリ
Help Center および File Exchange で Loops and Conditional Statements についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!