J. Wacks
J. Wacks

Reputation: 33

Looking for a way to vectorize find command in Matlab

I am looking for a faster way to use the find command without loops and nothing that I have found so far has helped me. Here is a simplified example of what I am trying to do:

A = [0.1,0.8,1;
     0.3,0.7,1;
     0.2,0.3,1]; % this is a square matrix with cumulated sums of probabilities in its rows
row_sel = [2,3,2]; % this is a vector containing the rows of A that I am interested in
index = NaN(length(A),1);
for i = 1:length(A)
    index(i) = find(A(row_sel(i),:)>rand,1,'first'); % I want to get the index of the first column of row row_sel(i) whose element exceeds a random number
end

Unfortunately, something like

index_mat = find(A(row_sel,:)>rand(length(A),1),1,'first')

does not do the trick. Thanks for any help!

Upvotes: 3

Views: 96

Answers (2)

Luis Mendo
Luis Mendo

Reputation: 112659

You can compare A indexed by row_sel_ with a column vector of random values, exploiting implicit expansion; and then use the second output of max, which gives the index of the first maximum value along the specified dimension:

[~, index] = max(A(row_sel,:) > rand(numel(row_sel),1), [], 2);

For Matlab before R2016b there is no implicit expanstion, but you can use bsxfun:

[~, index] = max(bsxfun(@gt, A(row_sel,:), rand(numel(row_sel),1)), [], 2);

Upvotes: 3

HansHirse
HansHirse

Reputation: 18895

The one-liner:

size(A, 2) + 1 - sum(A(row_sel, :) > rand(size(A, 1), 1), 2)

Explanation

As you already figured out

A(row_sel, :) > rand(size(A, 1), 1)

gets you the wanted comparison between your values and some random numbers. Let's say this is

ans =
    0  1  1
    0  0  1
    0  1  1

Then

sum(A(row_sel, :) > rand(size(A, 1), 1), 2)

counts the occurences of 1s in the result per row, so here it is

ans =
    2
    1
    2

Now, let's get the total number of elements per row

size(A, 2)

Just substract the amount of found 1s, and you will get the first index per each row. (We have to add 1, because we want the first occurrence.)

size(A, 2) + 1 - sum(A(row_sel, :) > rand(size(A, 1), 1), 2)

Upvotes: 3

Related Questions