Initialize a 3D matrix and add new data - matlab

Here the code that i have as example:
aaa = [];
bbb = [];
for ii = 1:10
[aaa(:,:,end+1), bbb(:,end+1)] = myfunction();
end
The function myfunction:
function [aaa, bbb] = myfunction()
aaa = rand(5,3);
bbb = rand(5,1);
end
I know i could use ii for sending the output from the variables to aaa and bbb like [aaa(:,:,ii), bbb(:,ii)] = myfunction(). I'm just curious to know why for aaa i generate a 5x3x11 matrix (shouldn't it be 5x3x10?)?. For bbb, it correctly generates a 5x10 matrix. Hence, why the end + 1 works for bbb and not aaa?

I believe this has to do with how MATLAB defines an empty matrix. If you do size(aaa), MATLAB will return 0 0, as you would expect. size(bbb) returns the same. However, if you explicitly try to find the size of the 3rd dimension using size(aaa,3), MATLAB returns 1. So it appears that MATLAB defines an empty matrix as having zero size in the first two dimensions, and a size of 1 in all the other dimensions.
What this means is that when you do a(:,:,end+1), you're actually accessing a(:,:,2), because the end of the 3rd dimension of a is 1, even when it is empty. You don't have this problem with b, because it is only two dimensional, and the end of the second dimension of an empty matrix is zero.
EDIT: As an aside, you should always pre-allocate your matrices if you're going to be assigning values to them in a loop (MATLAB will have complained about this, I believe). If you don't, the matrices have to be resized on every loop iteration, generally resulting in a slower execution time.

I found a solution to my problem. In order to have end+1 work for the third dimension, aaa should be declared as follow:
aaa = zeros(0,0,0);
See this link for further explication on why this works.

Related

Vectorization of a small code snippet

q=
2
4
6
1
6
8
From=
1
4
2
To=
3
6
3
q is a sequence of points. For instance, q(From(1):To(1)) gives 2,4,6. I want to vectorize this example.
This is non-vectorized working code:
J=3;
L=cell(J,1);
for j=1:J
L{j}=q(From(j):To(j));
end
Its result is:
L=
2,4,6 % j=1
1,6,8 % j=2
4,6 % j=3
I cannot figure out how to get a vectorized form of this code. I tried to convert L into 2-dim array, but anyway nothing works.
You can get rid of the for loop by using arrayfun to apply a specific function on all elements of the inputs. However, I'm not sure if it will be much faster than the loopy version.
The code below produces output equivalent to your original cell array L:
L2 = arrayfun(#(x,y)q(x:y), From, To, 'UniformOutput', false);
Here, #(x,y)q(x:y) defines an anonymous function that returns subvectors from q according to the inputs x and y, which are picked by arrayfun from your input vectors From and To.
As suggested in the comments, if you desire extra genericity you can specify another function handle like this:
L_fun = #(q)arrayfun(#(x,y)q(x:y), From, To, 'uniformoutput', false);
...and then call it for an arbitrary vector (not necessarily your original q) as such:
q2 = rand(10,1); %// Random vector for testing
Lout = L_fun(q2); %// Use From and To to pick from q2
Or even define a handle which takes all inputs:
L_fun = #(q,From,To)arrayfun(#(x,y)q(x:y), From, To, 'uniformoutput', false);
but in this case it might be better to actually write a named function already.

In an assignment A(:) = B, the number of elements in A and B must be the same

if (hidden_layer>1)
for i =1 :hidden_layer
start_hidden_layer(i) = rand([gk(i+1),(gk(i)+1)])-0.5 ;
end
end
hi Friends.
I know every iteration was changed start_hidden_layer matrix dimensional.But all start_hidden_layer values must saved. How to solve this problem?
firstly hidden_layer>1
gk(i) is integer value for example 5 , 3, 8
Since you're calling rand with different matrix sizes on each iteration, you cannot save the results into a normal matrix. You need to use a cell matrix to store the result, like this:
%//preallocate the cell array
start_hidden_layer = cell(1, hidden_layer);
for i = 1:hidden_layer
start_hidden_layer{i} = rand([gk(i+1), (gk(i)+1)]) - 0.5;
end
For more on cell arrays and how to use them, see this Mathworks help doc.

Create matrix of matrix by loading data "MATLAB"

I want make a vector of matrix with loading data of text file.
I am using cat.
n : number of matrices.
p : number of columns of matrices.
every matrix has 4 row.
for example I have 1200 numbers in one text file and p is 3, so n=100.
How can make it?!
This is what I tried to do:
X = cat(n,[1...p; ; ; ],...,[ ; ; ; ]);
The description is a bit vague, but here is what I would recommend:
Read all the data into matlab (It seems like you know how to do this)
Put everything in one big matrix or vector
Only after putting everything together, use the reshape command
In your case you may want to do something like this for step 3:
raw = rand(1200,1); %Assuming your data looks something like this
X = reshape(raw,[],4,3);
For 1200 values this will give you a 100x4x3 answer. Just make sure it is a nice multiple of 4x3 if you apply reshape like this.
Update
Apparently this was the variation the asker was looking for, a 4x3x100 matrix:
X =reshape(r,4,3,100)
If you know the number of matrices (n), you can store it into a cell array like this
myCellArray = cell(n,1);
for it = 1:n
myCellArray{it} = (...) %Load matrix whatever how you do it (Load, fread,...)
end
or just by using dynamic allocation, but not really efficient,
myArray = [];
myArray = [myArray newLoadArray];

gathering specific rows from each submatrices or cell arrays

I hope to gather last lines from each submatrix or cell arrays.
I have 17 x 20 cells in matrix name A.
Each submatrices have different number of lines, but same number of columns (total 7 columns, all)
I tried to generate a file, made up of only last rows of each submatrices. My target file's from will be
M = [column1 column2 column3 column4 column5 column6 column7]
% made up of last rows of each submatrices, unknown number of lines, 7 columns
So I tried
for x_cc = 1:20
for y_cc = 1:17
M = A{x_cc, y_cc}(end,:);
end
end
But it is not working, giving the error Subscript indices must either be real positive integers or logicals.
Should I need to define the size first? What operation should be done? or what commands are useful? I tried cellfun, but not sure how can I use here.
Need any help to solve this situation. Thanks~!
First off, it looks like you switched x_cc and y_cc. Since your matrix is 17 x 20, x_cc is the rows and should go to 17, while y_cc will go to 20.
However, the error you're getting is probably coming from trying to index an empty array (one of those contained in A) using end. An example of this error:
a = [];
a(end)
??? Subscript indices must either be real positive integers or logicals.
If you're curious, a method avoiding for loops would look like:
B = cellfun(#(x) x(end,:), A, 'UniformOutput', 0);
M = cell2mat(B(:));
This grabs the last row from each matrix in A, then stacks them vertically and transforms to an array.

How to change row number in a FOR loop... (MATLAB newbie)

I have a set of data that is <106x25 double> but this is inside a struct and I want to extract the data into a matrix. I figured a simple FOR loop would accomplish this but I have hit a road block quite quickly in my MATLAB knowledge.
This is the only piece of code I have, but I just don't know enough about MATLAB to get this simple bit of code working:
>> x = zeros(106,25); for i = 1:106, x(i,:) = [s(i).surveydata]; end
??? Subscripted assignment dimension mismatch.
's' is a very very large file (in excess of 800MB), it is a <1 x 106 struct>. Suffice it to say, I just need to access a small portion of this which is s.surveydata where most rows are a <1 x 25 double> (a row vector IIRC) and some of them are empty and solely return a [].
s.surveydata obviously returns the results for all of the surveydata contained where s(106).surveydata would return the result for the last row. I therefore need to grab s(1:106).surveydata and put it into a matrix x. Is creating the matrix first by using x = zeros(106,25) incorrect in this situation?
Cheers and thanks for your time!
Ryan
The easiest, cleanest, and fastest way to write all the survey data into an array is to directly catenate it, using CAT:
x = cat(1,s.surveydata);
EDIT: note that if any surveydata is empty, x will have fewer rows than s has elements. If you need x to have the same amount of rows as s has elements, you can do the following:
%# find which entries in s have data
%# note that for the x above, hasData(k) contains the
%# element number in s that the k-th row of x came from
hasData = find(arrayfun(#(x)~isempty(x.surveydata),s));
%# initialize x to NaN, so as to not confuse the
%# real data with missing data entries. The call
%# to hasData when indexing makes this robust to an
%# empty first entry in s
x = NaN(length(s),length(s(hasData(1)).surveydata);
%# fill in only the rows of x that contain data
x(hasData,:) = cat(1,s(hasData).surveydata);
No, creating an array of zeroes is not incorrect. In fact it's a good idea. You don't have to declare variables in Matlab before using them, but for loops, pre-allocating has speed benefits.
x = zeros(size(s), size(s(1)));
for i = 1:106
if ~isempty(s(i).surveydata)
x(i, :) = s(i).surveydata;
end
end
Should accomplish what you want.
EDIT: Since OP indicated that some rows are empty, I accounted for that like he said.
what about this?
what s is?
if s(i).surveydata is scalar:
x = zeros(106,25);
for i = 1:106
x(i,1) = [s(i).surveydata];
end
I am guessing that is what you want tough it is not clear at all :
if s(i).surveydata is row vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata];
end
if s(i).surveydata is column vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata]';
end