How can I get a 'random index' of unique elements in a matrix rather than first/last index ?

5 vues (au cours des 30 derniers jours)
For eg , I have a matrix
M = [2;2;2;2;2;1;1;1;1;3;5;5;5;5;6;6;4;4;4]
So when I apply,
[C, ia, ~] = unique(M)
I will get
C = [1;2;3;4;5;6]
ia = [6;1;10;17;11;15];
Always first index of each unique element is returned by default. If 'last' is given as argument, the last index will be returned.
Instead I would like to get random index,
For eg ,
ia = [8;3;10;19;12;16]
I tried below code snippet which works. Each time random index of unique values are returned, but as the matrix size increases the process gets slower.
M = [2;2;2;2;2;1;1;1;1;3;5;5;5;5;6;6;4;4;4]
iq = unique(M);
randIx = zeros(numel(iq,1));
idxMatrix = 1:numel(M);
for i = 1:numel(iq)
labelIdx = idxMatrix(M==iq(i));
randomLabel = randi(numel(labelIdx));
randIdx(i) =labelIdx(randomLabel);
end
randIdx
Is there a better way than this which is faster ? Please comment if you need any clarification about the question.

Réponse acceptée

Bruno Luong
Bruno Luong le 21 Nov 2018
p = randperm(length(M));
[C,ia,~] = unique(M(p));
ia = p(ia)

Plus de réponses (2)

Arunkumar M
Arunkumar M le 21 Nov 2018
M = [2;2;2;2;2;1;1;1;1;3;5;5;5;5;6;6;4;4;4];
[C, ia, ~] = unique(M);
randIdx = [];
for i = 1:length(C)
randIdx = [randIdx; randi([min(find(M == C(i))) max(find(M == C(i)))],1,1)];
end
  1 commentaire
Varun Pai
Varun Pai le 21 Nov 2018
Thank you for your time. But this would give wrong result if M is slightly changed to
M = [2;2;2;2;2;1;1;1;1;3;5;2;5;5;6;6;4;1;4];

Connectez-vous pour commenter.


Andrei Bobrov
Andrei Bobrov le 21 Nov 2018
Modifié(e) : Andrei Bobrov le 21 Nov 2018
M = [2;2;2;2;2;1;1;1;1;3;5;5;5;5;6;6;4;4;4];
[~,b,c] = unique(M);
out = round(rand(numel(b),1).*(accumarray(c,1) - 1)) + b;
ADD
M = [2;2;2;2;2;1;1;1;1;3;5;2;5;5;6;6;4;1;4];
[a,b,c] = unique(M,'stable');
[~,jj] = sort(a);
[z,ii] = sort(c);
out = ii(round(rand(numel(a),1).*(accumarray(z,1) - 1))+find([true;diff(z)==1]));
out = out(jj);
  2 commentaires
Varun Pai
Varun Pai le 21 Nov 2018
Modifié(e) : Varun Pai le 21 Nov 2018
Thanks for your time. It works for above matrix.
Could you please check the result for M = [2;2;2;2;2;1;1;1;1;3;5;2;5;5;6;6;4;1;4] ? There is a chance that indices of certain unique elements could be missed.
When I executed your statement for
M = [2;2;2;2;2;1;1;1;1;3;5;2;5;5;6;6;4;1;4];
I got result as
out = 7
3
10
18
13
15
Here 7 and 18 corresponds to '1', whereas there is no index returned for '4'.
Edit : I got a solution. I created a new matrix initially by appending the index. I sorted the matrix based on first column. Then I applied your logic and extracted the index using 'out';
N = sortrows([M [1:numel(M)]'],1) ;
[~,b,c] = unique(N);
out = round(rand(numel(b),1).*(accumarray(c,1) - 1)) + b;
out2 = N(out,2);

Connectez-vous pour commenter.

Catégories

En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by