I'm facing a problem. I have a zeros matrix 600x600. I need to fill this matrix with 1080 1s randomly. Any suggestions?
Or, use the intrinsic routine randperm thusly:
A = zeros(600);
A(randperm(600^2,1080)) = 1;
A = sparse(600,600); %// set up your matrix
N=1080; %// number of desired ones
randindex = randi(600^2,N,1); %// get random locations for the ones
while numel(unique(randindex)) ~= numel(randindex)
randindex = randi(600^2,N,1); %// get new random locations for the ones
end
A(randindex) = 1; %// set the random locations to 1
This utilises randi to generate 1080 numbers randomly between 1 and 600^2, i.e. all possible locations in your vectors. The while loop is there in case it happens that one of the locations occurs twice, thus ending up with less than 1080 1.
The reason you can use a single index in this case for a matrix is because of linear indexing.
The big performance difference with respect to the other answers is that this initialises a sparse matrix, since 1080/600^2 = 0.3% is very sparse and will thus be faster. (Thanks to #Dev-iL)
This is one way to do it,
N = 1080; % Number of ones
M = zeros(600); % Create your matrix
a = rand(600^2,1); % generate a vector of randoms with the same length as the matrix
[~,asort] = sort(a); % Sorting will do uniform scrambling since uniform distribution is used
M(asort(1:N)) = 1; % Replace first N numbers with ones.
Related
How can I get a maximum of a three-dimensional matrix (which was previously two-dimensional and converted to a three-dimensional matrix by reshape) in MATLAB so that I can then get the position of that maximum value in the matrix?
I wrote the following code, but unfortunately the dimensions obtained for the maximum values are larger than the dimensions of the matrix.
mxshirin=max(max(frvrdin))
[X,Y,Z]=size(frvrdin)
[o,i]=find(frvrdin==mxshirin)
xo=size(o)
xi=size(i)
If frvrdin is 3D, max(max(frvrdin)) will be a 1x1x3 vector:
frvrdin = rand(3,3,3);
max(max(frvrdin))
ans(:,:,1) =
0.8235
ans(:,:,2) =
0.9502
ans(:,:,3) =
0.7547
Don't nest max() functions, simply use the 'all' switch to take the max of the entire matrix at once.
max(frvrdin,[],'all')
ans =
0.9340
If you're on an older MATLAB, use column flattening: max(frvrdin(:)).
You can't use the automated location output of max [val,idx]=max() on more than two dimensions, so use find and ind2sub:
frvrdin = rand(3,3,3);
val = max(frvrdin,[],'all'); % Find maximum over all dims
idx = find(abs(frvrdin-val)<1e-10); % Compare within tolerance
[row,col,page] = ind2sub(size(frvrdin),idx); % Get subscript indices
where row is the index into your first dimension, col into the second and finally page into the third.
I am using Matlab function round(rand(256)) to create a square matrix of size 256x256 with random distribution of 0s and 1s.
What I specifically want to do is that I want to somehow specify number of 1s that rand() (or any other relevant function for that matter) to generate and distribute throughout the matrix randomly
Magdrop’s answer is the most straight-forward method, it computes the percentile of the random values to determine the threshold.
Another two options involve randperm:
Randomly permute all indices into the matrix, then threshold:
sz = [256,256]; % matrix size
n = 256; % number of zeros
M = randperm(prod(sz)) <= n;
M = reshape(M,sz);
Randomly permute indices and select n as the locations of the ones:
indx = randperm(prod(sz),n);
M = zeros(sz);
M(indx) = 1;
You could also generate the random value the usual way, but before you round them, sort them as a vector. The number of 1s will the index in the sorted vector you want to cut for 1s or 0s. For example, let say we want 50 1s:
matrix = rand(256,256);
vec = sort(reshape(matrix,[],1));
thresh = vec(50);
matrix(matrix <= thresh) = 1;
matrix(matrix > thresh) = 0;
You could use the randi function to determine the locations of where to insert the ones, and then place those ones into your matrix. For example for n ones:
matrix = zeros(256,256);
onesIndices = randi([0 256*256],1,n);
matrix(onesIndices) = 1;
One problem with this approach is that randi can generate repeat values, though for this example, where the size of the matrix is large and the number of ones is low, this is pretty unlikely. You could test if this is the case and "reroll:" so if sum(sum(matrix)) is less than n you know you had a repeat value.
Edit: a better approach is to use randperm instead of randi and only take the first n elements. This should prevent there from being repeats and having to re-roll.
I need to generate all square matrices of order n with given properties.
Matrices are symmetric.
Entries are 0 and 1.
Diagonal elements are zeros.
I am using Matlab2012b. Can you help me with the code?
I was trying to write it down. It needs a long sequences of for loops. Any simpler technique?
Try this:
N = 4; %// matrix size
M = (N^2-N)/2; %// number of values to fill in each matrix
P = 2^M; %// number of matrices
x = dec2bin(0:P-1)-'0'; %// each row contains the values of a matrix, "packed" in a vector
result = NaN(N,N,P); %// preallocate
for k = 1:P
result(:,:,k) = squareform(x(k,:)); %// unpack values
end
The matrices are result(:,:,1), result(:,:,2) etc.
Say we have a matrix m x n where the number of rows of the matrix is very big. If we assume each row is a vector, then how could one find the maximum/minimum distance between vectors in this matrix?
My suggestion would be to use pdist. This computes pairs of Euclidean distances between unique combinations of observations like #seb has suggested, but this is already built into MATLAB. Your matrix is already formatted nicely for pdist where each row is an observation and each column is a variable.
Once you do apply pdist, apply squareform so that you can display the distance between pairwise entries in a more pleasant matrix form. The (i,j) entry for each value in this matrix tells you the distance between the ith and jth row. Also note that this matrix will be symmetric and the distances along the diagonal will inevitably equal to 0, as any vector's distance to itself must be zero. If your minimum distance between two different vectors were zero, if we were to search this matrix, then it may possibly report a self-distance instead of the actual distance between two different vectors. As such, in this matrix, you should set the diagonals of this matrix to NaN to avoid outputting these.
As such, assuming your matrix is A, all you have to do is this:
distValues = pdist(A); %// Compute pairwise distances
minDist = min(distValues); %// Find minimum distance
maxDist = max(distValues); %// Find maximum distance
distMatrix = squareform(distValues); %// Prettify
distMatrix(logical(eye(size(distMatrix)))) = NaN; %// Ignore self-distances
[minI,minJ] = find(distMatrix == minDist, 1); %// Find the two vectors with min. distance
[maxI,maxJ] = find(distMatrix == maxDist, 1); %// Find the two vectors with max. distance
minI, minJ, maxI, maxJ will return the two rows of A that produced the smallest distance and the largest distance respectively. Note that with the find statement, I have made the second parameter 1 so that it only returns one pair of vectors that have this minimum / maximum distance between each other. However, if you omit this parameter, then it will return all possible pairs of rows that share this same distance, but you will get duplicate entries as the squareform is symmetric. If you want to escape the duplication, set either the upper triangular half, or lower triangular half of your squareform matrix to NaN to tell MATLAB to skip searching in these duplicated areas. You can use MATLAB's tril or triu commands to do that. Take note that either of these methods by default will include the diagonal of the matrix and so there won't be any extra work here. As such, try something like:
distValues = pdist(A); %// Compute pairwise distances
minDist = min(distValues); %// Find minimum distance
maxDist = max(distValues); %// Find maximum distance
distMatrix = squareform(distValues); %// Prettify
distMatrix(triu(true(size(distMatrix)))) = NaN; %// To avoid searching for duplicates
[minI,minJ] = find(distMatrix == minDist); %// Find pairs of vectors with min. distance
[maxI,maxJ] = find(distMatrix == maxDist); %// Find pairs of vectors with max. distance
Judging from your application, you just want to find one such occurrence only, so let's leave it at that, but I'll put that here for you in case you need it.
You mean the max/min distance between any 2 rows? If so, you can try that:
numRows = 6;
A = randn(numRows, 100); %// Example of input matrix
%// Compute distances between each combination of 2 rows
T = nchoosek(1:numRows,2); %// pairs of indexes for all combinations of 2 rows
for k=1:length(T)
d(k) = norm(A(T(k,1),:)-A(T(k,2),:));
end
%// Find min/max distance
[~, minIndex] = min(d);
[~, maxIndex] = max(d);
T(minIndex,:) %// Displays indexes of the 2 rows with minimum distance
T(maxIndex,:) %// Displays indexes of the 2 rows with maximum distance
Having a mask with size MxN containing 0 and 1.
How to select randomly (uniform distributed) select n 1-pixels of this mask?
Edit:
I want to select n pixels of this mask where the mask is 1. Those n pixel should be randomly distributed over the whole image/mask.
Locate the indexes of the "1"s in your matrix, and then use randperm to select a random subset of those:
idx = find(mask==1);
y = randperm(length(idx),n); %take n values from 1 to the number of values in idx
rand_idx = idx(y); %select only those values out of your indexes
Another concise solution is possible with randi for allowing repeated samples (sampling with replacement):
nonZeroSampleInds = randi(nnz(mask),1,n);
maskInds = find(mask);
maskSampleInds = maskInds(nonZeroSampleInds);
For non-repeating samples, randperm works as in nkjt's answer or just for fun you could start with the following,
[~,nonZeroSampleInds]=sort(rand(1,nnz(mask)));
I think MATLAB's randperm is perfect for the job, but this sort line is actually how MATLAB used to implement randperm.m before it became a MEX-file, so I thought I would offer it up because I love a little MATLAB trivia.
If you want the locations in order, sort either nonZeroSampleInds or maskSampleInds.
You can do something like :
idx = find( mask == 1); % This found all 1s in your mask
idx2Take = 1:5:size(idx,1); % This take 1s on every 5 (uniform distributed)
uniformPts = idx(idx2Take); % Finally, obtain the mask position from the uniform distribution
So after, you just need to get all uniformPts.