Indicator matrix in Matlab - matlab

In matlab, I have a double datatype variable named Label with dimension 1211 x 1.
I would like to create a IndicatorMatrix(6 columns) such that if a row in the Label variable is 34 then the corresponding row in the IndicatorMatrix should be 0 0 1 1 0 0.
I mean 1 # 3 and 4th column of Indicator matrix.

Let x be the 1211x1 matrix (Label), and let im (IndicatorMatrix) be the matrix you wish to create. Do:
h = size(x,1);
im = [zeros(h, 2), repmat(x == 34, 1, 2), zeros(h, 2)];
This creates a matrix which is a horizontal concatentation of a zero matrix with 2 columns and height h, then a boolean matrix of x == 34 (which has 1 where x was 34, and zero in other places) repeated 2 times horizontally and once vertically, and then again another zero matrix.
Note that in your case we could have replaces h by 1211, but I tried to write more generic code.

Related

Average matrices in a cell array within a structure Matlab

In Matlab I have a structure AVG of size 1 x 6 which has one field averageNEST that is a cell array also of size 1 x 6.
Each averageNEST contains matrices of varying sizes (in one dimension), so for example
AVG(1).averageNEST{1,1} is of size 281 x 3 x 19 and
AVG(1).averageNEST{1,2} is of size 231 x 3 x 19
The 2nd and 3rd dimensions of the matrices are always 3 and 19, it is only the first dimension that can change.
I want to average over all the matrices contained within AVG(1).averageNEST and obtain one matrix of size X x 3 x 19 where X is the size of the smallest matrix in AVG(1).averageNEST.
Then I want to do this for all 6 averageNEST in AVG - so have a separate averaged matrix for AVG(1), AVG(2) ... AVG(6).
I have tried multiple things including trying to concatenate matrices using the following code:
for i=1:6
min_epoch = epoch + 1;
for ii=1:19
averageNEST(:,:,ii) = [AVG(i).averageNEST(1:min_epoch,:,ii)];
end
end
and then average this but it doesn't work and now I'm really confused about what I'm doing!
Can anyone help?
I am not sure if I understand what you want to do. If you want to keep only the elements up to the size of the the smallest matrix and then average those matrices you can do the following:
averageNEST = cell(size(AVG));
for iAVG = 1:numel(AVG)
nests = AVG(iAVG).averageNEST;
minsize = min(cellfun(#(x) size(x,1), nests));
reducednests = cellfun(#(y) y(1:minsize, :, :), nests, 'UniformOutput', false);
averageNEST{iAVG} = sum(cat(4, reducednests{:}), 4) / numel(nests);
end

Assign value to the third column of a matrix for specific first and second column values

The matrix A looks like this:
1 1.1 0
2 1.2 0
3 1.3 0
4 1.1 0
5 1.5 0
1 1.0 0
2 0.9 0
3 0.3 0
4 0.1 0
5 0.4 0
The first column represents X while 2nd represents Y and 3rd Z. As you could see, x values gets repeated every 5 samples.
and Z column is all zeros, I did some calculation and I want to add a value at specific X and Y value. How can i do it ?
For example if you want to insert an z = 5 value for x = 4 and y = 0.1,
You could do
maskRow = A(:,1) == 4 & A(:,2) == 0.1;
A(maskRow,3) = 5
Explanation:
In the first line of the code, we find which rows of the matrix satisfies both the condition. i.e comparing x with the first column and Y with the second column of matrix A. The maskRow gives logicals of true corresponding the row which satisfies both the above conditions while false for rest of the rows.
In the second line of the code, we assign z values to the third column of the particular row we obtained from the rowMask
An alternative to manually checking each column (could be useful if you have many columns) is to use ismember
maskRow = ismember(A(:,1:2), [4, 0.1], 'rows')
Another advantage of this method is that you can search for multiple different matches at onces:
maskRow = ismember(A(:,1:2), [4, 0.1; 2, 1.2], 'rows')

access cell array by two vector not pairwise

If I have a Cell array 2*2 where A{i,j} is a matrix, and I have two vectors v=1:2,c=1:2.
I want A(v,c) to return only A{1,1} and A{2,2} but matlab returns every combination of the two(aka also returns A{1,2} and A{2,1}).
Is there a way without using loops or cellfun ?
What I suspect you are doing is something like this:
B = A(v, c);
When you specify vectors to index into A, it finds the intersection of coordinates and gives you those elements. As such, with your indexing you are basically returning all of the elements in A.
If you want just the top left and lower right elements, use sub2ind instead. You can grab the column-major indices of those locations in your cell array, then slice into your cell array with these indices:
ind = sub2ind(size(A), v, c);
B = A(ind);
Example
Let's create a sample 2 x 2 cell array:
A = cell(2,2);
A{1,1} = ones(2);
A{1,2} = 2*ones(2);
A{2,1} = 3*ones(2);
A{2,2} = 4*ones(2);
Row 1, column 1 is a 2 x 2 matrix of all 1s. Row 1, column 2 is a 2 x 2 matrix of 2s, row 2 column 1 is a 2 x 2 matrix of all 3s and the last entry is a 2 x 2 matrix of all 4s.
With v = 1:2; c=1:2;, running the above code gives us:
>> celldisp(B)
B{1} =
1 1
1 1
B{2} =
4 4
4 4
As you can see, we picked out the top left and bottom right entries exactly.
Minor Note
If it's seriously just a cell array of 2 x 2, and you only want to pick out the top left and lower right elements, you can just do:
B = A([1 4]);
sub2ind would equivalently return 1 and 4 as the column major indices for the top left and lower right elements. This avoids the sub2ind call and still achieves what you want.

Creating a 1000 x 2 matrix where one column is constant and the other alternating

I would like to create a 1000 x 2 matrix where the first column consists of all 1's while the second column alternates between 2,0,2,0... . So, the matrix will consist of 1000 1's in the first column and alternating with 500 2's and 500 0's in the second column. How, using MATLAB, can I create this matrix?
To build the first column, use the function ones. To build the second column, first define the piece [2 0]', a two-element column vector, and use repmat to repeat it 500 times along the first dimension. Finally, use the concatenation operators [] to put the two columns together.
m = [ones(1000, 1), repmat([2 0]', 500, 1)]
Alternatively, you can do this:
m = repmat([1 2; 1 0], 500, 1);
We create a base matrix: A = [1 2; 1 0];, then stack this 500 times to create the matrix you desire.
If you don't like the repmat method, another way would be to create a matrix of ones which is 1000 x 2 long, then take the second column and add this with an alternating [1 -1] sequence that spans 1000 rows:
m = ones(1000,2);
m(:,2) = m(:,2) + (-1).^(0:999).';
We can even go mathematical and make the first column all ones, and the second column be:
y = 1 + cos(pi*x)
x would be an integer starting from 0 up to N-1 where N is the total number of rows you want. When x is even, cos(pi*x) = 1 and when x is odd, cos(pi*x) = -1. By adding this with 1, depending on what value x is, we will alternate between 2 and 0:
m = [ones(1000,1) 1 + cos(pi*(0:999)).'];

Creating Individual Matrix based on Label Matrix from DataMatrix

Let label be a matrix of size N x 1 (type double) and data be a matrix of size N x M (type double). The entries in the Label matrix looks like [ 1; 23; 135; ....; 6] which conveys that the
First row in the data matrix belongs to label 1
Second row in the data matrix belongs to label 2 and label 3
Third row in the data matrix belongs to label 1, label 3 and label 5 and so on
I would like to create a cell array say Individual{i} which stores all those rows from the data matrix which belongs to label i as given by the label matrix.
The resultant Individual{i} matrix will be size N_i x M.
Is there any efficient way to do the thing rather than looping row by row of data and label matrix?
I would turn your matrix label into a Boolean matrix L:
L = [ 1 0 0 0 0 0 ;
0 1 1 0 0 0 ;
1 0 1 0 1 0 ;
...
0 0 0 0 0 1 ];
for your example. You can use a sparse matrix if N or the number of labels is very large.
Then I think what you call N_i is sum(L(:, i)) and L' * data would compute the sum of all the rows in data with label L.
What do you want to do with the data once it's reached the Individual cell array? There's almost certainly a better way to do it...
Given the correct variables: N, M, data, label as you described, here's a sample code that creates the desired cell array Individual:
%# convert labels to binary-encoded format (as suggested by #Tom)
maxLabels = 9; %# maximum label number possible
L = false(N,maxLabels);
for i=1:N
%# extract digits of label
digits = sscanf(num2str(label(i)),'%1d');
%# all digits should be valid label indices
%assert( all(digits>=1) && all(digits<=maxLabels) );
%# mark this row as belong to designated labels
L(i,digits) = true;
end
%# distribute data rows according to labels
individual = cell(maxLabels,1);
for i=1:maxLabels
individual{i} = data(L(:,i),:);
end