Reputation: 472
I would like to extract (square) sub-matrices from a matrix, randomly with a size between some min and max values.
I would also like to retain the row and column indices which were selected.
Are there any built-in functions for this purpose? I would appreciate any general algorithm to achieve the desired results.
Just for an example without considering the square matrix constraint:
Input:
| 1 2 3 4 5 6 7 8 <- column indices
--+----------------
1 | 4 3 1 4 0 1 0 1
2 | 2 0 1 5 6 3 2 0
3 | 5 5 0 6 7 8 9 0
4 | 2 3 5 6 7 9 0 1
^
Row indices
Output sample:
| 1 4 5 7 8 <- column indices
--+----------
1 | 4 4 0 0 1
2 | 2 5 6 2 0
4 | 2 6 7 0 1
^
Row indices
Edit: I would like to have a function like this
matrixsample(numberOfSamples, minSize, maxSize, satisfyingFunction)
the samples should vary their size between the minSize
and maxSize
.
If numberOfSamples = 10, minSize = 2 and maxSize = 6
then output should be randomly selected rows and columns like:
sampleMatrix1 2x2 sampleMatrix2 3x3 sampleMatrix3 5x5 ... sampleMatrix7 6x6 ... sampleMatrx10 4x4
satisfyingFunction
could test any attribute of the matrix; like being non-singular, rank > x
, etc.
Upvotes: 1
Views: 745
Reputation: 30146
In MATLAB, you will find the randperm
function useful for selecting random rows/columns.
To get a randomly sized sub-matrix, use randi([minVal, maxVal])
to get a random integer between minVal
and maxVal
.
M = randi([0,9],4,8); % 4x8 matrix of random 1 digit integers, your matrix here!
nRows = randi([2, 4]); % The number of rows to extract, random between 2 and 4
nCols = randi([5, 7]); % The number of columns to extract, random between 5 and 7
idxRows = sort(randperm(size(M,1), nRows)); % Random indices of rows
idxCols = sort(randperm(size(M,2), nCols)); % Random indices of columns
output = M(idxRows, idxCols); % Select the sub-matrix
If you want to make the sub-matrix square then simply use the same value for nRows
and nCols
.
Showing this method works with your example input/output values:
M = [4 3 1 4 0 1 0 1; 2 0 1 5 6 3 2 0; 5 5 0 6 7 8 9 0; 2 3 5 6 7 9 0 1];
idxRows = [1 2 4]; idxCols = [1 4 5 7 8];
output = M(idxRows, idxCols)
% >> 4 4 0 0 1
% 2 5 6 2 0
% 2 6 7 0 1
You can package the above up into a short function, which returns the row and column indices, as well as the submatrix.
function output = getsubmatrix(M, nRows, nCols)
% Get a submatrix of random rows/columns
idxRows = sort(randperm(size(M,1), nRows));
idxCols = sort(randperm(size(M,2), nCols));
submatrix = M(idxRows, idxCols);
output = {submatrix, idxRows, idxCols};
end
Then you can use this in some sampling function as you described:
function samples = matrixsample(matrix, numberOfSamples, minSize, maxSize, satisfyingFunction)
% output SAMPLES which contains all sample matrices, with row & column indices w.r.t MATRIX
samples = cell(numberOfSamples,1);
% maximum iterations trying to satisfy SATISFYINGCONDITION
maxiters = 100;
for ii = 1:numberOfSamples
iters = 0; submatrixfound = false; % reset loop exiting conditions
nRows = randi([minSize, maxSize]); % get random submatrix size
nCols = nRows; % Square matrix
while iters < maxiters && submatrixfound == false
% Get random submatrix, and the indices
submatrix = getsubmatrix(matrix, nRows,nCols);
% satisfyingFunction MUST RETURN BOOLEAN
if satisfyingFunction(submatrix{1})
samples{ii} = submatrix; % If satisfied, assign to output
submatrixfound = true; % ... and move on!
end
iters = iters + 1;
end
end
end
Test example:
s = matrixsample(magic(10), 5, 2, 8, @(M)max(M(:)) < 90)
Upvotes: 2
Reputation: 18838
If the table
is given, you will do it by randsample
:
minRowVal = 3;
maxRowVal = 4;
minColVal = 2;
maxColVal = 4;
kRow = randi([minRowVal maxRowVal]) ;
kCol = randi([minColVal maxColVal]);
table(sort(randsample(size(table,1),kRow)),sort(randsample(size(table,2),kCol))
choose some sample by the given size of kRow
and kCol
, then select the information from the table.
Upvotes: 0