I am trying to eliminate a loop from an operation. If it can't be done, I'm trying to understand why using a loop to create a string command for eval is so much faster than doing the more conventional calculation.
Info
This question is closed. Reopen it to edit or answer.
Show older comments
I have a large matrix, X , of size k by m filled with i.i.d. random integers from 1 to n (for some variable n<k). I want to collect the indices of all columns that contain each integer from 1 to n at least once. I essentially want to execute:
my_indices = any(X==1) & any(X==2) & ... & any(X==n);
Obviously, without knowing n I cannot take this approach and even for fixed but large n, I might not want to write such a long line of code. I'm curious if there is a clever way to do this without any loop.
Also, if it requires a loop, is it better to use a loop to create a string for the command, or is it better to use a loop to just execute each one of the any operations and combine it with the previous results?
So, for example, both of the following approaches coded below give the same result. I was surprised to see that the first is an order of magnitude faster for some values of m although behavior is inconsistent (even though I've never had any good luck with eval before).
n = 6; %maximum possible random integer
k = 10; %number of rows of X
m = 1e6; %number of columns of X
X = ceil(n*rand(k,m));
%This approach creates a string for the command I want to execute and uses eval
str = [ ]; %empty string
for i=1:n %loop over
str = [ str 'any( X== ' num2str(i) ' ) & ']; %concatenate pieces
end
str = str(1:end-2); %remove the final &
my_indices = eval( str ); %execute the string
%This approach avoids using eval
my_indices2 = true(1,m);
for i=1:n
my_indices2 = my_indices2 & any(X==i);
end
Answers (2)
James Tursa
on 2 Jul 2015
Edited: James Tursa
on 2 Jul 2015
Assuming you want the indexes themselves:
n = whatever;
C = mat2cell(X,size(X,1),ones(1,size(X,2)));
my_indices = find(cellfun(@(x)numel(unique(x)),C) == n);
If you want a logical vector of size m that has the result, then don't do the "find" in the last line.
Star Strider
on 2 Jul 2015
One possibility:
X = randi(20, 50);
Xm = max(X(:));
X_col = [];
for k1 = 1:size(X,2)
C = unique(X(:,k1)); % Unique Values In Column ‘k1’
if size(C,1) == Xm
X_col = [X_col k1]; % If ‘Xm’ Unique Values, Store ‘k1’
end
end
The ‘X_col’ vector has the column indices of the columns that have ‘Xm’ unique values, that is at least one of every random number in the sequence.
This question is closed.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!