Home vectorising multiple calls of Matlab 'find'
Reply: 3

vectorising multiple calls of Matlab 'find'

physioConfusio
1#
physioConfusio Published in 2018-02-14 00:31:34Z

I make a large number of calls to the 'find' function of Matlab. For example, the following should give the essence:

x=rand(1,10^8);
indx=zeros(1,10^8);
for i=1:10^8
    indx(i) = find([0.2, 0.52, 0.76,1] < x(i), 1, 'last');
end

Is there a way to vectorize this code to speed it up? Just including x as a vector creates an error. If vectorization is not possible, then any other suggestions for speed would be appreciated. The actual problem I wish to solve has a considerably longer vector in the place of [0.2, 0.52, 0.76,1], so any solution shouldn't depend on the specific vector I provided.

thanks.

crjones
2#
crjones Reply to 2018-02-14 01:20:43Z

Based on your example, you may want to consider using the discretize function for this:

x=rand(1,10^8);
edges = [0.2, 0.52, 0.76, 1];
indx = discretize(x, edges, 'IncludedEdge', 'right'); 

Note that cases outside of the range will result in NaN.

% small test case
% x = [0.5198, 0.0768, 0.6788, 0.9496]
% indx = discretize(x, edges, 'IncludedEdge', 'right')
% answer:   1   NaN   2     3

Of course, this will only be applicable if you're trying to find where x fits in a well-ordered set.

Sardar Usama
3#
Sardar Usama Reply to 2018-02-14 09:29:26Z

Compare your vector with x to get a logical matrix indicating the values lesser in vec than x. Multiply that logical matrix with column vector representing the column subscripts. Use max to find the maximum (last) index that satisfies the inequality. For the case where inequality doesn't satisfy, you will get zero.

vec = [0.2, 0.52, 0.76, 1];    %Your vector
indx = bsxfun(@lt, vec(:), x); %Making 'vec' a column matrix and comparing with 'x'
indx = max(bsxfun(@times, indx, (1:numel(vec)).')); %The required result

With R2016b and later versions, you can use implicit expansion instead of bsxfun:

indx = vec(:) < x ;  
indx = max(indx .* (1:numel(vec)).');
gnovice
4#
gnovice Reply to 2018-02-14 04:51:29Z

For MATLAB versions R2015a and newer, the answer from crjones gives the best option using discretize:

edges = [0.2, 0.52, 0.76, 1];
indx = discretize(x, edges, 'IncludedEdge', 'right');

Any values in x outside the range of edges will have NaN for their indices.


For MATLAB versions R2014b and newer you can also use histcounts:

[~, ~, indx] = histcounts(x, edges);

The differences with discretize are that you can also get the count of values in each bin (the first output), and indices for values in x outside the range of edges will be 0.


For MATLAB versions prior to R2014b you can use histc (deprecated in newer versions):

[~, indx] = histc(x, edges);

Again, you can also get the count of values in each bin (the first output), and indices for values in x outside the range of edges will be 0.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.302939 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO