MATLAB: Хранение нескольких случайных строк в матрице, которые удовлетворяют определенным условиям

У меня есть матрица в Matlab, которая выглядит примерно так, за исключением тысяч строк:

A =

     5     6     7     8
     6     1     2     3
     5     1     4     8
     5     2     3     7
     5     8     7     2
     6     1     3     8
     5     2     1     6
     6     3     2     1

Я хотел бы получить матрицу, которая имеет три случайные строки с 5 в первом столбце и три случайные строки с 6 в первом столбце. Так что в этом случае выходная матрица будет выглядеть примерно так:

A =

     5     6     7     8
     6     1     2     3
     5     2     3     7
     6     1     3     8
     5     2     1     6
     6     3     2     1

Строки должны быть случайными, а не только первые три или последние три в исходной матрице. Я не совсем уверен, с чего начать, поэтому любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ: Это самая успешная попытка, которую я когда-либо делал. Я нашел все строки с 5 в первом столбце:

BLocation = find(A(:,1) == 5);
B = A(BLocation,:);

Затем я пытался использовать 'randsample', как это, чтобы найти три случайных строки из B:

C = randsample(B,3);

Но "randsample" не работает с матрицей.

Я также думаю, что это можно сделать немного эффективнее.

2 ответа

Решение

Вам нужно бежать randsample в строке индексы, удовлетворяющие условиям, т. е. равенство 5 или 6.

n = size(A,1);

% construct the linear indices for rows with 5 and 6 
indexA = 1:n; 
index5 = indexA(A(:,1)==5);
index6 = indexA(A(:,1)==6);

% sample three (randomly) from each 
nSamples = 3;
r5 = randsample(index5, nSamples);
r6 = randsample(index6, nSamples);

% new matrix from concatenation 
B = [A(r5,:); A(r6,:)];

Обновление: вы также можете использовать find заменить первоначальную конструкцию индекса, как предложил юк, которая оказывается быстрее (и оптимизирована!).

Bechmark (MATLAB R2012a)

A = randi(10, 1e8, 2); % 10^8 rows random matrix of 1-10

tic;
n = size(A,1);
indexA = 1:n;
index5_1 = indexA(A(:,1)==5);
toc

tic;
index5_2 = find(A(:,1)==5);
toc

Elapsed time is 1.234857 seconds.
Elapsed time is 0.679076 seconds.

Вы можете сделать это следующим образом:

desiredMat=[];
mat1=A(A(:,1)==5,:);
mat1=mat1(randperm(size(mat1,1)),:);
desiredMat=[desiredMat;mat1(1:3,:)];
mat1=A(A(:,1)==6,:);
mat1=mat1(randperm(size(mat1,1)),:);
desiredMat=[desiredMat;mat1(1:3,:)];

Приведенный выше код использует логическую индексацию. Вы также можете сделать это с find функция (логическое индексирование всегда быстрее, чем find).

Другие вопросы по тегам