Question

I have a matrix in Matlab which looks similar to this, except with thousands of rows:

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

I would like to get out a matrix that has three random rows with a '5' in the first column and three random rows with a '6' in the first column. So in this case, the output matrix would look something like this:

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

The rows must be random, not just the first three or the last three in the original matrix. I'm not really sure how to begin this, so any help would be greatly appreciated.

EDIT: This is the most successful attempt I've had so far. I found all the rows with a '5' in the first column:

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

Then I was trying to use 'randsample' like this to find three random rows from B:

C = randsample(B,3);

But 'randsample' does not work with a matrix.

I also think this could be done a little more efficiently.

Was it helpful?

Solution

You need to run randsample on the row indices that satisfy the conditions, i.e. equality to 5 or 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,:)];

Update: You can also use find to replace the original index construction, as yuk suggested, which proves to be faster (and optimized!).

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.

OTHER TIPS

You can do this as follows:

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,:)];

The above code uses logical indexing. You can also do this with find function (logical indexing is always faster than find).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top