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

4 Ansichten (letzte 30 Tage)
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.

Akzeptierte Antwort

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

Weitere Antworten (2)

Arunkumar M
Arunkumar M am 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 Kommentar
Varun Pai
Varun Pai am 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];

Melden Sie sich an, um zu kommentieren.


Andrei Bobrov
Andrei Bobrov am 21 Nov. 2018
Bearbeitet: Andrei Bobrov am 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 Kommentare
Varun Pai
Varun Pai am 21 Nov. 2018
Bearbeitet: Varun Pai am 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);

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by