O.T.
O.T.

Reputation: 147

vectorizing a check of minimum index in MATLAB

I have a vector named 'r' of 201 real values, and another vector named 'knots' of 21 real values. I want to find for each of the 'r' values the index i of the smallest 'knot' value which is greater than the 'r' value. Do I have to do it in a 'for' loop over the 'r' vector, or is there a way I can vectorize the code so I can avoid the for loop?

Upvotes: 0

Views: 55

Answers (1)

rayryeng
rayryeng

Reputation: 104474

Nope you can avoid loops. You can use bsxfun combined with max. I don't know what shape r and knots is in ... if they're row or column vectors, so I'm going to make the code independent of this fact. Take note that what I'm going to write assumes that there is at least one element in r where a value in knots is larger than r. If it isn't, then this code won't work.

Something like this is what I have in mind:

rs = r(:).'; %// Make sure r a row vector '
[knotss,indk] = sort(knots(:)); %// Make sure knots a column vector

%// Make sure that the values are sorted
%// For each value in knots, find all values that are greater than r
check = bsxfun(@gt, knotss, rs);

%// Determine the right indices for each value of knots in sorted array
[~,indc] = max(check, [], 1);

%// Get the original indices
indices = indk(indc);

The first two lines of code make sure that r is a row vector and knots is a column vector. We also sort the values in knots because you want to find the smallest value of knots that is greater than a value in r. It allows us to make things more efficient. I also return the actual ordering of knots because when we find the locations of the smallest value in knots that is greater than some value r, we have to refer back to the original order.

Next, the call to bsxfun creates a 2D Boolean matrix check. Each column in check is for each value in knots. Specifically, each column tells you which values of knots are greater than a value in r. For each column, false means that the corresponding value in r is not greater than the value in knots you're looking at and true is otherwise. Once you find this matrix, you call max and check over each column independently. When calling max, only the first time the maximum value is encountered gets returned. Because the Boolean matrix only consists of zeroes and ones, this effectively gives you the first time a true value is encountered per row, which denotes the smallest possible index that r can be that is greater than each value in knots.

You don't need to look at the actual maximum values, but you want the indices of where this maximum occurred, hence the variable indices is created and is the second output from max.


Here's a quick example with some test data:

r = [-1 0];
knots = [3 -1 1 0 -3];

Running through the above code, I get this for my indices:

indices =

     4
     3

This makes sense. The first value of r is -1, and the value in knots that is the smallest possible value where knots is greater than -1 is the value 0, which is in location 4. The second value of r is 0, and the value in knots that is the smallest possible value where knots is greater than 1 is 1, and is in location 3.

Upvotes: 1

Related Questions