How to perform logical AND on intervals of contiguous locations
1 回表示 (過去 30 日間)
古いコメントを表示
Arturo Camacho Lozano
2020 年 9 月 23 日
コメント済み: Arturo Camacho Lozano
2020 年 9 月 30 日
I have the following problem. Let's say I have the arrays
x = logical([0, 1, 0,0, 1,1, 0,0,0, 1,1,1, 0])
y = logical([0, 1, 1,0, 1,1, 0,1,0, 1,0,1, 0])
Array X has three intervals of 1's with indices 2:2, 5:6, and 10:12. I want to apply an "interval AND" operation to X, based on Y, in the following sense: for each interval of ones in X, if any element in Y is zero in that interval, the whole interval is zeroed, i.e., Z = intervalAND(X,Y) should be the same as
z = logical([0, 1, 0,0, 1,1, 0,0,0, 0,0,0, 0])
Let me explain. Since all(Y(2:2)) = 1, it produces ones in Z(2:2). The same happens in the second interval (5:6): Both Y(5) and Y(6) are true, producing ones in Z. However, there is a zero in Y(10:12) which zeroes the whole interval Z(10:12).
I know how to do it with a for loop:
d = diff(x);
pos = find(d == 1);
neg = find(d == -1);
z = x;
for k = 1:length(neg)
interval = pos(k)+1 : neg(k);
if ~all(y(interval))
z(interval) = false;
end
end
However, I need to vectorize it to make it run faster (I am working with huge arrays). Does someone know how to compute Z without using a for/while loop?
4 件のコメント
James Tursa
2020 年 9 月 24 日
Is the algorithm running on each column individually, or running across the entire matrix as a whole? I.e., does the 1's logic extend across columns?
採用された回答
Bruno Luong
2020 年 9 月 24 日
編集済み: Bruno Luong
2020 年 9 月 25 日
x = logical([0, 1, 0,0, 1,1, 0,0,0, 1,1,1, 0])
y = logical([0, 1, 1,0, 1,1, 0,1,0, 1,0,1, 0])
code without loop or groupping, on my bench test about 3 time faster than Stephen's accumarray solution
i = find(diff([0 x 0]));
n = histc(find(~y), i);
j = [1;-1]*(n(1:2:end)==0);
if x(end)
i(end)=[];
j(end)=[];
end
z = logical(cumsum(accumarray(i(:),j(:),[length(x),1])));
10 件のコメント
Bruno Luong
2020 年 9 月 26 日
編集済み: Bruno Luong
2020 年 9 月 26 日
Faster. It does not create unecessary elements to accumulate then removed.
The one before is still OK if you prefer readable code.
その他の回答 (2 件)
Mohammad Sami
2020 年 9 月 24 日
You can group based on the values of x.
gid = cumsum(x ~= circshift(x,1));
if(gid(1) == 0)
gid = gid + 1;
end
a = splitapply(@min,y,gid);
z = a(gid);
1 件のコメント
Matt J
2020 年 9 月 25 日
Using group1s from
>> xg=group1s(x)+1;
>> yg=splitapply(@all,y,xg);
>> z=yg(xg)
z =
1×13 logical array
0 1 0 0 1 1 0 0 0 0 0 0 0
0 件のコメント
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!