replace non-zero values with random numbers - matlab

I have a zero-one matrix in MATLAB as follows:
[0 0 0 1 1 1
0 1 1 0 0 0
1 0 0 0 0 1
1 1 1 0 0 0
0 0 0 1 0 1]
I want to define another matrix including rand values instead of indexes of above matrix by 1. For instance the desired new rand matrix should be:
[0 0 0 0.2 0.2 0.1
0 0.6 0.7 0 0 0
0.4 0 0 0 0 0.6
0.7 0.8 0.5 0 0 0
0 0 0 0.3 0 0.4]
I used a two nested loop for to find non-zero values from first matrix and replace the rand values instead of them in a new matrix.
Is there any function of matlab to do it automatically, without using two nested loop for?

You can do it as follows:
A = ...
[0 0 0 1 1 1;
0 1 1 0 0 0;
1 0 0 0 0 1;
1 1 1 0 0 0;
0 0 0 1 0 1];
B = rand(size(A));
A(logical(A)) = B(logical(A));
A =
0 0 0 0.1320 0.2348 0.1690
0 0.3377 0.3897 0 0 0
0.9027 0 0 0 0 0.7317
0.9448 0.3692 0.4039 0 0 0
0 0 0 0.0598 0 0.4509
(I just took the basic rand-function, adjust it, as you need it)

You can slightly improve thewaywewalk's answer by generating only as many random numbers as you need. As a bonus, this approach allows to do everything in one line:
A(logical(A)) = rand(1,nnz(A));

If you're trying to replace the ones in matrix A with random numbers then you don't need any looping at all.
Here's one method.
a = double(rand(5,5)>.5); % Your binary matrix should be type double.
n = sum(a(:)); % Count the 1's.
a(a>0) = rand(1,n); % Replace the ones with rands.

If 'l' is a matrix containing zeros and non-zeros. Consider the scenarios below answering this question :
Replace all the zeros in matrix with random numbers :
l(l==0) = randn(1,size(l(l==0),1));
Replace all the positive values with random numbers :
l(l>0) = randn(1,size(l(l>0),1));
Replace all the negative values with random numbers :
l(l<0) = randn(1,size(l(l<0),1));
Replace all the 'NaN' with random numbers.
l(isnan(l)) = randn(1,size(l(isnan(l)),1));

Related

How to randomly select x number of indices from a matrix in Matlab

I'm trying to generate a randomly scattered but limited number of 1's in a matrix of zeros efficiently.
Say I have a 10x10 matrix of zeros (zeros(10)) and I want to randomly place ten 1's so it looks like:
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
How can I do this WITHOUT a for-loop and without manually plugging in each position (this example is a much smaller version of my real problem)?
My code so far:
% Generate zeros
M = zeros(10)
% Generate random indices
Rands = [randsample(10, 10) randsample(10, 10)]
Where the first column is intended to be the row indices and the second column the column indices.
Now I obviously can't just drop these indices into the row and column indices of M like this:
M(Rands(:,1), Rands(:,2)) = 1
How can I vecorise the changes to these random indices?
You can use randperm to randomly generate the linear indices to be filled with 1:
sz = [10 10]; % desired size
n = 10; % desired number of ones
M = zeros(sz);
M(randperm(prod(sz), n)) = 1;
Alternatively, you can use randperm and reshape in one line:
M = reshape(randperm(prod(sz))<=n, sz);
You can use sub2ind to convert subscripts to linear index:
M(sub2ind(size(M),Rands(:,1),Rands(:,2)))=1

How to delete all columns in matrix containing zeros in some rows in MATLAB

I have a matrix whose size is 4x16 and I need to remove all columns which have the value of first row is zero. For example: here is the matrix example :
X = [1 0 0 0; 0 1 0 0; 0 0.4 0 0; 0 0 0 0.8; 0.5 0 0 0];
The 2D matrix (X) looks like this:
1 0 0 0
0 1 0 0
0 0.4 0 0
0 0 0 0.8
0.5 0 0 0
So what I need is just X = [1 0 0 0;0.5 0 0 0 ] because the first row of these columns are different of Zero.
Just exclude that row numbers:
X = X(X(:,1) ~= 0, :);
X(:,1) ~= 0 is a boolean vector for the first column which is true if the value of the element would not be 0.

I'm using MATLAB R2015b, How do we generate a rectangular matrix with upper diagonal elements 1?

I am trying to generate a rectangular matrix with 1s on the diagonal above the main diagonal and -1s on the main diagonal. I used "eye" which does not create the diagonal above the main.
Please find my attempt to this below.
N = 5
M1 = -eye([N-1 N])
M2 = eye([N N-1])'
M = M1+M2
I am unable to resolve this issue on my own. Any help or links to relevant documentation would be greatly appreciated.
I don't know of any prebuild function, but you can easily make such a matrix yourself:
N=5;
M=7;
diag=-eye(N,M);
upper_diag=horzcat(zeros(N,1),eye(N,M-1))
final=diag+upper_diag
using the identity matrix and some concatenation to shift the diagonal around. This example assumes you are looking for a square matrix.
The result looks like:
final =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0
Just create eye and diag matrices as per normal, add them together, then chop away the rows you do not need:
nCol = 7;
nRow = 5;
M = -eye(nCol) + diag(ones(nCol - 1, 1), 1);
M = M(1:nRow, 1:nCol)
produces
M =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0
The four-input version of spdiags does just that, producing a sparse matrix. You may need to convert to full then.
M = 5; %// number of rows
N = 7; %// number of columns
d = [0 1]; %// specify main diagonal and the one above
v = [-1 1]; %// values in those diagonals
result = full(spdiags(ones(M,1)*v, d, M, N));
This gives
result =
-1 1 0 0 0 0 0
0 -1 1 0 0 0 0
0 0 -1 1 0 0 0
0 0 0 -1 1 0 0
0 0 0 0 -1 1 0

Creating MATLAB neural network target array from class labels [duplicate]

For neural networking, I would like to represent a column vector y = [1;2;3] in a matrix like so:
y = [1 0 0;
0 1 0;
0 0 1]
My vector y is very large, and so hardcoding is not an option. Also, I would like to avoid using for-loops.
What I did so far:
y1 =[y; zeros(1,length(y)) ;zeros(1,length(y))] % add two rows with zeros in orde to give y the right format
idx = find(y1(1,:) == 2); % find all the columns containing a 2
y1(:,idx(1):idx(end)) = y1(:,[0;1;0]); % this does not work because now I am comparing a matrix with a vector
I also tried this:
y1( y1 == [2;0;0] )=[0;1;0]; % This of course does not work
Is there a way to specify I want to compare columns in y1 == [2;0;0], or is there another way to solve this?
From the context of your question, you wish to find a matrix where each column is an identity vector. For an identity vector, each column in this matrix is a non-zero vector where 1 is set in the position of the vector denoted by each position of y and 0 otherwise. Therefore, let's say we had the following example:
y = [1 5 4 3]
You would have y_out as the final matrix, which is:
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
There are several ways to do this. The easiest one would be to declare the identity matrix with eye, then let y pick out those columns that you want from this matrix and place them as columns into your final matrix. If y had all unique values, then we would simply be rearranging the columns of this identity matrix based on y. As such:
y_out = eye(max(y));
y_out = y_out(:,y)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
Another way would be to declare a sparse matrix, where each row index is simply those elements from y and each column index is increasing from 1 up to as many elements as we have y:
y_out = sparse(y, 1:numel(y), 1, max(y), numel(y));
y_out = full(y_out)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
One more way would be to use sub2ind to find linear indices into your matrix, then access those elements and set them to 1. Therefore:
ind = sub2ind([max(y) numel(y)], y, 1:numel(y));
y_out = zeros(max(y), numel(y));
y_out(ind) = 1
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
This works even if y has "missing" values:
n = numel(y);
y_matrix = zeros(n, max(y));
y_matrix((1:n) + (y-1)*n) = 1;
Example:
y = [1 5 3 2];
gives
y_matrix =
1 0 0 0 0
0 0 0 0 1
0 0 1 0 0
0 1 0 0 0
You can use bsxfun:
y_out = bsxfun(#eq, (1:max(y)).', y);
Not as efficient as the #rayryeng's answer but this might also help,
Also if there are repeated values in y this code works fine.
a = [1 2 3 2 5 7 6 8];
[X,Y] = meshgrid(a,1 : length(a));
A = X == Y;
A =
1 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1

Get the indexes of the boundary cells of a subset of a matrix. Matlab

Given a matrix where 1 is the current subset
test =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Is there a function, or quick method to get change the subset to the boundary of the current subset?
Eg. Get this subset from 'test' above
test =
0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 0
0 1 1 1 1 0
0 0 0 0 0 0
In the end I just want to get the minimum of the cells surrounding a subset of a matrix. Sure I could loop through and get the minimum of the boundary (cell by cell), but there must be a way to do it with the method i've shown above.
Note the subset WILL be connected, but may not be rectangular. This may be the big catch.
This is a possible subset.... (Would pad this with a NaN border)
test =
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 1 1 1 1
0 0 1 1 1 1
Ideas?
The basic steps I'd use are:
Perform a dilation on the shape to get a new area which is the shape plus its boundary
Subtract the original shape from the dilated shape to leave just the boundary
Use the boundary to index your data matrix, then take the minimum.
Dilation
What I want to do here is pass a 3x3 window over each cell and take the maximum value in that window:
[m, n] = size(A); % assuming A is your original shape matrix
APadded = zeros(m + 2, n + 2);
APadded(2:end-1, 2:end-1) = A; % pad A with zeroes on each side
ADilated = zeros(m + 2, n + 2); % this will hold the dilated shape.
for i = 1:m
for j = 1:n
mask = zeros(size(APadded));
mask(i:i+2, j:j+2) = 1; % this places a 3x3 square of 1's around (i, j)
ADilated(i + 1, j + 1) = max(APadded(mask));
end
end
Shape subtraction
This is basically a logical AND and a logical NOT to remove the intersection:
ABoundary = ADilated & (~APadded);
At this stage you may want to remove the border we added to do the dilation, since we don't need it any more.
ABoundary = ABoundary(2:end-1, 2:end-1);
Find the minimum data point along the boundary
We can use our logical boundary to index the original data into a vector, then just take the minimum of that vector.
dataMinimum = min(data(ABoundary));
You should look at this as morphology problem, not set theory. This can be solved pretty easily with imdilate() (requires the image package). You basically only need to subtract the image to its dilation with a 3x3 matrix of 1.
octave> test = logical ([0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 1 1 1 1
0 0 1 1 1 1]);
octave> imdilate (test, true (3)) - test
ans =
0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 1
0 1 0 0 0 0
0 1 0 0 0 0
It does not, however, pads with NaN. If you really want that, you could pad your original matrix with false, do the operation, and then check if there's any true values in the border.
Note that you don't have to use logical() in which case you'll have to use ones() instead of true(). But that takes more memory and has worse performance.
EDIT: since you are trying to do it without using any matlab toolbox, take a look at the source of imdilate() in Octave. For the case of logical matrices (which is your case) it's a simple usage of filter2() which belongs to matlab core. That said, the following one line should work fine and be much faster
octave> (filter2 (true (3), test) > 0) - test
ans =
0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 1
0 1 0 0 0 0
0 1 0 0 0 0
One possible solution is to take the subset and add it to the original matrix, but ensure that each time you add it, you offset its position by +1 row, -1 row and +1 column, -1 column. The result will then be expanded by one row and column all around the original subset. You then use the original matrix to mask the original subet to zero.
Like this:
test_new = test + ...
[[test(2:end,2:end);zeros(1,size(test,1)-1)],zeros(size(test,1),1)] + ... %move subset up-left
[[zeros(1,size(test,1)-1);test(1:end-1,2:end)],zeros(size(test,1),1)] + ... %move down-left
[zeros(size(test,1),1),[test(2:end,1:end-1);zeros(1,size(test,1)-1)]] + ... %move subset up-right
[zeros(size(test,1),1),[zeros(1,size(test,1)-1);test(1:end-1,1:end-1)]]; %move subset down-right
test_masked = test_new.*~test; %mask with original matrix
result = test_masked;
result(result>1)=1; % ensure that there is only 1's, not 2, 3, etc.
The result for this on your test matrix is:
result =
0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 1
0 1 0 0 0 0
0 1 0 0 0 0
Edited - it now grabs the corners as well, by moving the subset up and to the left, up and to the right, down then left and down then right.
I expect this would be a very quick way to achieve this - it doesn't have any loops, nor functions - just matrix operations.