1

With a geographical grid the size 20x30, I have two (temperature) variables:

The data A with the size 20x30x100
and a threshold the size 20x30

I'd like to apply the threshold to the data, i.e. to cut out the values in A that are above threshold, with every grid point having its own threshold. Since that will give a different number of values for each grid point, I thought to pad the rest with zeros, so that the resulting variable, let's call it B, will also be of the size 20x30x100.

I was thinking to do something like this, but there's something wrong with the loop:

B = sort(A,3); %// sort third dimension in ascending order
threshold_3d = repmat(threshold,1,1,100); %// make threshold into same size as B

for i=1:20
    for j=1:30
        if B(i,j,:) > threshold_3d(i,j,:); %// if B is above threshold
          B(i,j,:); %// keep values
        else
          B(i,j,:) = 0; %// otherwise set to zero
        end
    end
end

What is the correct way to do the loop?
What other options to do this are there?

Thanks for any help!

Kim H
  • 13
  • 2

1 Answers1

2

You can use bsxfun for a much more efficient solution which will internally take care of the replication being done with repmat, like so -

B = bsxfun(@times,B,bsxfun(@gt,B,threshold))

A more efficient solution might be to use logical indexing to set the False elements from the mask created by bsxfun(gt, i.e. True ones with the use of bsxfun(@le in B to zeros thereby avoiding the use of bsxfun(@times, which for huge multidimensional arrays could be a bit expensive, like so -

B(bsxfun(@le,B,threshold)) = 0

Note on efficiency : Being a relational operation, going with the vectorized operation with bsxfun would provide both memory and runtime efficiency. The memory efficiency part has been discussed here - BSXFUN on memory efficiency with relational operations and the performance numbers have been researched here - Comparing BSXFUN and REPMAT.

Sample run -

 >> B
 B(:,:,1) =
      8     3     9
      2     8     3
 B(:,:,2) =
      4     1     8
      4     5     6
 B(:,:,3) =
      4     8     5
      5     6     5
 >> threshold
 threshold =
      1     3     9
      1     9     1
 >> B(bsxfun(@le,B,threshold)) = 0
 B(:,:,1) =
      8     0     0
      2     0     3
 B(:,:,2) =
      4     0     0
      4     0     6
 B(:,:,3) =
      4     8     0
      5     0     5
Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358