If I have an array of A = [10 1 5 20] I want a program to find indexes of the elements. In this case Idx = [3 1 2 4]. I am using [~,Idx]=sort([10 1 5 20]) and get the following:
Idx =
2 3 1 4
It's totally not what I expected. I even don't understand how the program got those numbers.
It is simple:
A = [10 1 5 20];
[~, Idx] = sort(A);
[~, orders] = sort(Idx);
% orders
% [3 1 2 4]
orders is your answer. You need to get the indices of sorted Idx.
Note that Idx(i) represents the index of i-th element in the original array A.
Related
This might be a basic question.
To find out the maximum value and its index in array in MATLAB, I have used this code:
A = [1 2 3; 4 5 6; 7 8 9]
[val, idx] = max(A, [], 2);
Now, how can I find the index array of all the element (not finding maximum)?
May be you are talking bout subindices and global indices. Read about sub2ind and ind2sub. Check the below demo:
A = [1 2 3; 4 5 6; 7 8 9] ;
[m,n] = size(A) ;
% sub indices
[J,I] = meshgrid(1:m,1:n) ;
% global indices
idx = sub2ind(size(A),I,J)
I want to find all possible variations (combinations) of a vector, choosing various numbers of elements from that vector.
For example, suppose I have the vector:
x = [1 2 3 4 5];
I can determine the number of combinations for each number of chosen elements:
x = [1 2 3 4 5]';
n = numel(x);
for k = 1:n
combs(k) = nchoosek(n,k);
end
sum(combs)
This results in:
combs = 5 10 10 5 1
sum(combs) = 31
I want a way to store all 31 of these combinations in an array, for example a cell array, with n cells, within each is an array in which each row is a vector combination of the elements.
e.g. at k = 4:
combs{4} =
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
Is there an existing function that does this, or what would be the most simple approach to this?
Call nchoosek with a vector as first input, using arrayfun (or equivalently for) to loop over the number of picked elements:
n = 5;
combs = arrayfun(#(k) nchoosek(1:n,k), 1:n, 'UniformOutput', false);
Here is an approach using dec2bin , find and accumarray:
x = [1 2 3 4 5];
[a b] = find(dec2bin(1:2^numel(x)-1)=='1');
combs = accumarray(a,x(b),[],#(c){c});
I have an array [2; 3] and a matrix [ 1 3 4 5; 2 4 9 2].
Now I would like to extract the second element from the first row and the third element from the second row and thus obtain [3 ; 9]. I managed it to do it with a loop, but since I'm working with much larger arrays, I would like to avoid these.
You can use sub2ind to convert each of the column subscripts (along with their row subscripts) into a linear index and then use that to index into your matrix.
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
% Compute the linear index using sub2ind
inds = sub2ind(size(A), (1:numel(cols)).', cols);
B = A(inds)
% 3
% 9
Alternately, you could compute the linear indices yourself which is going to be more performant than sub2ind
B = A((cols - 1) * size(A, 1) + (1:numel(cols)).');
% 3
% 9
By exploiting the diag function, you can obtain an elegant one-line solution:
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
B = diag(A(:,cols))
% 3
% 9
Here is what diag(A(:,cols)) does:
A(:,cols) selects the columns cols of A, with column k of A(:,cols) corresponding to the column cols(k) of A, giving [3 4; 4 9];
diag returns the diagonal entries of this matrix, thus returning at position k the k-th diagonal element of A(:,cols), which is A(k,cols(k)).
I have hit a brick wall trying to solve this:
Given a 5x1 cell array of vectors of indices to an array of n elements I need to find the reverse mapping.
What I have is the relation "In group 2, there are elements 15, 16, 17,...."
What I want to have is "Element 15 is member of group 2,4,5."
This is the structure of my cell array
myCellArray =
[1x228 double]
[1x79 double]
[1x136 double]
[1x93 double]
[1x81 double]
This is part of the contents of my index vector
myCellArray{2}(1:5) =
15 16 17 18 19
What I want is a cell array of n cells containing the indices of group membership for each element.
help?
You can do this with a combination of cellfun and arrayfun. First create a cell array:
>> mycellarray = { [1 2], [4 5], [3 4], [1 2 3 4 5] };
To get the elements of the cell array that contain a particular number (say 1) you can use cellfun:
>> find( cellfun(#(s)ismember(1, s), mycellarray) )
ans =
1 4
Which tells you that 1 is in the 1st and 4th elements of mycellarray. Now you can just map this over the list of all possible indexes using arrayfun. The arrays that are produced might be of different length, so we need to set 'UniformOutput' to false.
>> n = 5;
>> result = arrayfun(#(i)find(cellfun(#(s)ismember(i,s), mycellarray)), 1:n, ...
'UniformOutput', false);
The elements are the index vectors that you want --
>> result{1}
ans =
1 4 # since 1 is in the 1st and 4th array
>> result{3}
ans =
3 4 # since 3 is in the 3rd and 4th array
Do you have to use cell arrays to save space?
Otherwise can you change your current matrix to an MxN normal matrix where N is n as you have defined and M is the number of groups. And then just pad the end of each row with zeros. So it holds the same information but it makes your reverse query easy to do using find.
so if n = [1 2 3 4 5 6 7]
and we have 3 groups such that group 1 is [1 4 5], group 2 is [3] and group 3 is [1 2 6 7] your current matrix would be
M = 3; N = numel(n);
m = zeros(M,N);
m(1, 1:3) = [1 4 5];
m(2, 1) = 3;
m(3, 1:4) = [1 2 6 7];
now you want to know which group does the number i belong to. It's as simple as (updated based on Chris Taylor's observation)
find(any(m == i, 2))
I am trying to sort the columns of a matrix based on the another vector values in a
fast way in matlab.
Let assume I have a reference vector:
a = [1 8 3];
And the matrix I wanna sort by rows
b =[2 3 4
5 6 4
1 2 1];
And I want the result based on the vector a if the sorted a is
a = [8 3 1]
the sorted matrix will be now
b = [3 4 2
6 4 5
2 1 1];
So the index of the first vector is the same with the index of the columns
So we sort columns based on the values of the vector.
In Matlab the sort function returns two variables, the first is the sorted vector/matrix and the second is a set of indices that can be combined with the original data to produce the sorted values.
A = [ 5 4 1 2 3 ];
[A_sorted1, idx] = sort(A);
A_sorted2 = A(idx);
A_sorted1 and A_sorted2 are equivalent.
If the number of rows in b is equal to the number of elements in a then you can simply use:
[~, idx] = sort(a);
b_sorted = b(idx,:);
And if you want to sort by columns use:
b_sorted = b(:,idx);