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

조회 수: 5 (최근 30일)
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.

채택된 답변

Bruno Luong
Bruno Luong 2018년 11월 21일
p = randperm(length(M));
[C,ia,~] = unique(M(p));
ia = p(ia)

추가 답변 (2개)

Arunkumar M
Arunkumar M 2018년 11월 21일
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
Varun Pai
Varun Pai 2018년 11월 21일
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];

댓글을 달려면 로그인하십시오.


Andrei Bobrov
Andrei Bobrov 2018년 11월 21일
편집: Andrei Bobrov 2018년 11월 21일
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
Varun Pai
Varun Pai 2018년 11월 21일
편집: Varun Pai 2018년 11월 21일
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);

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Creating and Concatenating Matrices에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by