elimination of conscutive regions (generalization: ones with zeros between)

1 次查看(过去 30 天)

I need effectively eliminate (by zeroing) the consecutive "1's" between "-1's" and start/end of column at each column of matrix A, which now can be separated by any number of zeroes. The number of consecutive "1's" between "-1's" and start/end of column is > N. This is a non-trivial generalization of my previous Question.

Again, typical size(A) = [100000,1000].

See example:

A =
     1    -1     0
     0     1     1
     0     1     1
     1     1     0
     0     0     1
     1    -1     0
    -1     1     1
    -1     0    -1
     1     1     1
     0     1    -1

For N = 2 the expected result is

Aclean =
     0    -1     0
     0     0     0
     0     0     0
     0     0     0
     0     0     0
     0    -1     0
    -1     0     0
    -1     0    -1
     1     0     1
     0     0    -1

For N = 3 the expected result is

Aclean =
    1    -1     0
    0     1     0
    0     1     0
    1     1     0
    0     0     0
    1    -1     0
   -1     1     0
   -1     0    -1
    1     1     1
    0     1    -1
  4 个评论
Matt J
Matt J 2018-10-1
编辑:Matt J 2018-10-1
which now can be separated by any number of zeroes
This is the definition of non-consecutive. Why, then, are you saying the eliminated 1's are to be consecutive?

请先登录,再进行评论。

采纳的回答

Bruno Luong
Bruno Luong 2018-10-1
A = [1 -1 0;
0 1 1;
0 1 1;
1 1 0;
0 0 1;
1 -1 0;
-1 1 1;
-1 0 -1;
1 1 1;
0 1 -1];
N = 3;
[m,n] = size(A);
Aclean = A;
for j=1:n
Aj = [-1; A(:,j); -1];
i = find(Aj == -1);
c = histc(find(Aj==1),i);
b = c <= N;
im = i(b);
ip = i([false; b(1:end-1)]);
a = accumarray(im,1,[m+2,1])-accumarray(ip,1,[m+2,1]);
mask = cumsum(a);
mask(i) = 1;
Aclean(:,j) = Aclean(:,j).*mask(2:end-1);
end
Aclean
  3 个评论
Michal
Michal 2018-10-2
Is there any serious reason to still use old "histc" instead "histcounts"? Both functions has same performance and "histc" will be removed in future releases.

请先登录,再进行评论。

更多回答(2 个)

Michal
Michal 2018-10-1
编辑:Michal 2018-10-1
I am still looking for better (faster) solution. Any idea how to improve so far best solution:
A = [1 -1 0;
0 1 1;
0 1 1;
1 1 0;
0 0 1;
1 -1 0;
-1 1 1;
-1 0 -1;
1 1 1;
0 1 -1];
N = 3;
sep = A==-1;
sep(1,:) = true;
idx = cumsum(sep(:));
sep(1,:) = A(1,:)==-1;
num = accumarray(idx, A(:)==1);
iff = num <= N;
Aclean = reshape(sep(:)|iff(idx), size(A)) .* A;
Aclean
Big test matrix:
A = double(rand(100000,1000)>.4) - double(rand(100000,1000)>.65);
Bruno's code (N = 5): Elapsed time is 4.848747 seconds.
My code (N = 5): Elapsed time is 3.257089 seconds.
  13 个评论

请先登录,再进行评论。


Bruno Luong
Bruno Luong 2018-10-2
That's true, somehow it's a 1D scanning problem.
I think we are close to the limit of MATLAB can do, if faster speed is still needed, then one should go to MEX programming route instead of torturing MATLAB to squeeze out the last once of speed.

产品


版本

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by