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!