Create 'n' matrices in a loop [duplicate] - matlab

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to concatenate a number to a variable name in MATLAB?
Hi everyone, as the title, i'd like to learn if anyone knows how, in Matlab, create 'n' matrices in a loop.
Like this:
for (i=1:n)
p_i = P(i, :);
q_i = Q(i, :);
A_i = [p_i, p_i', q_i];
end
Matlab, of course, rewrites n times on the matrix A_i, but i would like to have n matrices of 'i' index.
Thank you in advance, have a good day!!

You could concatenate everything into a 3D array:
A_i = zeros(D1,D2,n); % D1 and D2 are the dimensions of the 2D arrays
for i = 1:n
p_i = P(i,:);
q_i = Q(i,:);
A_i(:,:,i) = [p_i, p_i', q_i];
end
If you genuinely want n distinct matrices, then you will need a cell array. Your code would become something like:
A_i = cell(1,n);
for i = 1:n
p_i = P(i,:);
q_i = Q(i,:);
A_i{i} = [p_i, p_i', q_i];
end
Note that you should carefully consider which would suit your needs the best. The only real advantage of a cell array is that it allows each element to be a different data-type, or a different-sized array. A 3D array has several advantages over a cell array of 2D arrays (you can sum over it, reshape it, slice 3D sub-chunks out of it, etc. etc.).

Related

Perform an operation on indexed/grouped elements of an array in Matlab [duplicate]

I'm working in Matlab.
I have a two-dimensional matrix with two columns. Lets consider elements in the first column as labels. Labels may be repeated.
How to multiply all elements in the second column for every label?
Example:
matrix = [1,3,3,1,5; 2,3,7,8,3]'
I need to get:
a = [1,3,5; 16,21,3]'
Can you help me with doing it without for-while cycles?
I would use accumarray. The preprocessing with unique assigns integer indices 1:n to the values in the first row, which allow accumarray to work without creating unnecessary bins for 2 and 4. It also enables the support for negative numbers and floats.
[ulable,~,uindex]=unique(matrix(:,1))
r=accumarray(uindex,matrix(:,2),[],#prod)
r=[ulable,r]
/You can also use splitapply:
[ulable,~,uindex]=unique(matrix(:,1))
r=splitapply(#prod,matrix(:,2),uindex)
r=[ulable,r]
You can do it without loops using accumarray and the prod function:
clear
clc
matrix = [1,3,3,1,5; 2,3,7,8,3]';
A = unique(matrix,'rows');
group = A(:,1);
data = A(:,2);
indices = [group ones(size(group))];
prods = accumarray(indices, data,[],#prod); %// As mentionned by #Daniel. My previous answer had a function handle but there is no need for that here since prod is already defined in Matlab.
a = nonzeros(prods)
Out = [unique(group) a]
Out =
1 16
3 21
5 3
Check Lauren blog's post here, accumarray is quite interesting and powerful!
Try something like this, I'm sure it can be improved...
unValues = unique(matrix(:,1));
bb = ones(size(unValues));
for ii = 1:length(unValues)
bb(ii) = bb(ii)*prod(matrix(matrix(:, 1) == unValues(ii), 2));
end
a = [unValues bb];

Finding indices of matrices while traversing

I have a matrix:
1|2|3|4
4|5|6|7
7|8|9|10
10|11|12|13
I want to multiply the indices of this matrix with indices of another matrix of different size:
7|8|9
9|10|10
10|11|11
for these two matrices I have used the following for loops:
for x=1:4
for y=1:4
for m=1:3
for n=1:3
c=(m*x+n*y);
end
end
end
end
Is there any way to rewrite the above code without using loops? If the indices of each element can be generated in the above matrices, I think it can be done. Please help
mx = m'*x;
mx = mx(:);
ny = n'*y;
ny = ny(:);
mxe = repmat(mx, [length(ny), 1]);
nye = repmat(ny, [length(mx), 1]);
c = mxe+nye;
This will result in c containing all the values that get put in during that loop you have there (note that in your loop, value gets assigned and overwritten).

How to crop matrix of any number of dimensions in Matlab?

Suppose I have 4D matrix:
>> A=1:(3*4*5*6);
>> A=reshape(A,3,4,5,6);
And now I want to cut given number of rows and columns (or any given chunks at known dimensions).
If I would know it's 4D I would write:
>> A1=A(1:2,1:3,:,:);
But how to write universally for any given number of dimensions?
The following gives something different:
>> A2=A(1:2,1:3,:);
And the following gives an error:
>> A2=A;
>> A2(3:3,4:4)=[];
It is possible to generate a code with general number of dimension of A using the second form of indexing you used and reshape function.
Here there is an example:
Asize = [3,4,2,6,4]; %Initialization of A, not seen by the rest of the code
A = rand(Asize);
%% This part of the code can operate for any matrix A
I = 1:2;
J = 3:4;
A1 = A(I,J,:);
NewSize = size(A);
NewSize(1) = length(I);
NewSize(2) = length(J);
A2 = reshape(A1,NewSize);
A2 will be your cropped matrix. It works for any Asize you choose.
I recommend the solution Luis Mendo suggested for the general case, but there is also a very simple solution when you know a upper limit for your dimensions. Let's assume you have at most 6 dimensions. Use 6 dimensional indexing for all matrices:
A1=A(1:2,1:3,:,:,:,:);
Matlab will implicit assume singleton dimensions for all remaining dimension, returning the intended result also for matrices with less dimensions.
It sounds like you just want to use ndims.
num_dimensions = ndims(A)
if (num_dimensions == 3)
A1 = A(1:2, 1:3, :);
elseif (num_dimensions == 4)
A1 = A(1:2, 1:3, :, :);
end
If the range of possible matrix dimensions is small this kind of if-else block keeps it simple. It seems like you want some way to create an indexing tuple (e.g. (1:2,:,:,:) ) on the fly, which I don't know if there is a way to do. You must match the correct number of dimensions with your indexing...if you index in fewer dimensions than the matrix has, matlab returns a value with the unindexed dimensions collapsed into a single array (similar to what you get with
A1 = A(:);

How to store a series of vectors from a for loop matlab [duplicate]

This question already has an answer here:
Subscript indices must either be real positive integers or logicals?
(1 answer)
Closed 8 years ago.
I have a for loop which generates a vector. i want to store these vectors in a matrix.
normally i would do:
for r=1:100
vec=[x:y]+r;
mat(:,r)=vec
end
But this doesnt work, because i have something like:
dr=10/20
for r=1:dr:20
vec=[x;y]+r;
...
How would I store the vectors in a matrix now? Because i cant use r for the column indices, because the values of r arent integers most of the time.
Many options eg:
r=1:dr:20
for rr=1:length(r)
vec=[x;y]+r(rr);
mat(:,rr)=vec;
...
or
col = 1;
for r=1:dr:20
vec=[x;y]+r;
mat(:,col)=vec;
col = col + 1;
....
But whatever you choose you must preallocate mat before your for loop like this:
mat = zeros(length(x) + length(y), length(1:dr:20))
Pre-allocation is essential when using loops in Matlab or they will run very inefficiently.

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];