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

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

Plus de réponses (2)

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

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

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);
Please see part ADD in my answer.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Matrices and Arrays dans Centre d'aide 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