Asked by Michal Kvasnicka
on 1 Oct 2018

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

Answer by Bruno Luong
on 1 Oct 2018

Accepted Answer

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

Bruno Luong
on 1 Oct 2018

Cleaner version

[m,n] = size(A);

Aclean = A;

for j=1:n

Aj = A(:,j);

im1 = find(Aj == -1);

i1 = find(Aj==1);

[c,loc] = histc(i1,[-Inf; im1; Inf]);

b = c > N;

Aclean(i1(b(loc)),j) = 0;

end

Michal Kvasnicka
on 2 Oct 2018

Bruno Luong
on 2 Oct 2018

No, I'm just used to HISTC.

Sign in to comment.

Answer by Michal Kvasnicka
on 1 Oct 2018

Edited by Michal Kvasnicka
on 1 Oct 2018

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.

Bruno Luong
on 2 Oct 2018

It's not the same thing than

~xor(Aclean, A)

Michal Kvasnicka
on 2 Oct 2018

Yes … nice simplification!

Bruno Luong
on 2 Oct 2018

And what about

mask = Aclean==A

?

Sign in to comment.

Answer by Bruno Luong
on 2 Oct 2018

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.

Opportunities for recent engineering grads.

Apply Today
## 4 Comments

## Image Analyst (view profile)

Direct link to this comment:https://uk.mathworks.com/matlabcentral/answers/421655-elimination-of-conscutive-regions-generalization-ones-with-zeros-between#comment_616580

## Michal Kvasnicka (view profile)

Direct link to this comment:https://uk.mathworks.com/matlabcentral/answers/421655-elimination-of-conscutive-regions-generalization-ones-with-zeros-between#comment_616590

## Matt J (view profile)

Direct link to this comment:https://uk.mathworks.com/matlabcentral/answers/421655-elimination-of-conscutive-regions-generalization-ones-with-zeros-between#comment_616593

## Michal Kvasnicka (view profile)

Direct link to this comment:https://uk.mathworks.com/matlabcentral/answers/421655-elimination-of-conscutive-regions-generalization-ones-with-zeros-between#comment_616596

Sign in to comment.