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
).