Matlab, matrix of arrays - arrays

There are 3 matrices A,B,C:
A=[0 1;2 3]
B=[4 5;6 7]
C=[8 9;10 11]
How to create a new matrix D(2,2) so as its elements are arrays of a type
D = [{A(1,1), B(1,1), C(1,1)} {{A(1,2), B(1,2), C(1,12};
{A(2,1), B(2,1), C(2,1)} {A(2,2), B(2,2), C(2,2)}]
For example: Using an operator D(1,1) gives the result
0, 4, 8
The bracket {} are only illustrative and do not represent a matlab syntax...

You could stack the matrices along the third dimension:
D = cat(3,A,B,C);
Then you could access as:
>> D(1,1,:)
ans(:,:,1) =
0
ans(:,:,2) =
4
ans(:,:,3) =
8
if you want to get a 1D-vector:
>> squeeze(D(1,1,:)) %# or: permute(D(1,1,:),[1 3 2])
ans =
0
4
8
If you prefer to use cell arrays, here is an easier way to build it:
D = cellfun(#squeeze, num2cell(cat(3,A,B,C),3), 'UniformOutput',false);
which can be accessed as:
>> D{1,1}
ans =
0
4
8

You are almost there:
D = [{[A(1,1), B(1,1), C(1,1)]} {[A(1,2), B(1,2), C(1,2)]};
{[A(2,1), B(2,1), C(2,1)]} {[A(2,2), B(2,2), C(2,2)]}]
(you see the additional branches?)
D is now a cell array, with each cell containing a 1x3 matrix.
To access the cell array use this syntax:
D{1,1}

Related

Generate vectors from single values in Matlab

I have vector c:
c = [2 5 3];
I want to generate vectors with their lengths equal to each value in c in a consecutive order. So, I should obtain 3 vectors:
c1 = [1 2];
c2 = [3 4 5 6 7];
c3 = [8 9 10];
Next, I want to align these vectors in a 1x3 cell array:
out = {c1 c2 c3};
This may seem straightforward, but I can't figure how to do it automatically. Any ideas?
You could use mat2cell to accomplish this. We first create an array from 1 to sum(c) and then use mat2cell to group the array into pieces where each piece is the size of each element of c.
out = mat2cell(1:sum(c), 1, c);
This reduces the need for intermediate variables and gives you your cell array directly.
out{1} =
1 2
out{2} =
3 4 5 6 7
out{3} =
8 9 10

Intersection of multiple arrays without for loop in MATLAB

I've always been told that almost all for loops can be omitted in MATLAB and that they in general slow down the process. So is there a way to do so here?:
I have a cell-array (tsCell). tsCell stores time-arrays with varying length. I want to find an intersecting time-array for all time-arrays (InterSection):
InterSection = tsCell{1}.time
for i = 2:length{tsCell};
InterSection = intersect(InterSection,tsCell{i}.time);
end
Here's another way. This also assumes there are no duplicates within each original vector.
tsCell_time = {[1 6 4 5] [4 7 1] [1 4 3] [4 3 1 7]}; %// example data (from Divakar)
t = [tsCell_time{:}]; %// concat into a single vector
u = unique(t); %// get unique elements
ind = sum(bsxfun(#eq, t(:), u), 1)==numel(tsCell_time); %// indices of unique elements
%// that appear maximum number of times
result = u(ind); %// output those elements
Here's a vectorized approach using unique and accumarray, assuming there are no duplicates within each cell of the input cell array -
[~,~,idx] = unique([tsCell_time{:}],'stable')
out = tsCell_time{1}(accumarray(idx,1) == length(tsCell_time))
Sample run -
>> tsCell_time = {[1 6 4 5],[4 7 1],[1 4 3],[4 3 1 7]};
>> InterSection = tsCell_time{1};
for i = 2:length(tsCell_time)
InterSection = intersect(InterSection,tsCell_time{i});
end
>> InterSection
InterSection =
1 4
>> [~,~,idx] = unique([tsCell_time{:}],'stable');
out = tsCell_time{1}(accumarray(idx,1) == length(tsCell_time));
>> out
out =
1 4

how to assemble vectors into matrix using for loop in MATLAB

I want to assemble a matrix from 5 vectors using a for loop in Matlab.
How can I do that? Or is there a simple alternative to do the same?
Here's an example: I have 5 vectors:
A = [1 2 3]
B = [1 2 3]
C = [1 2 3]
D = [1 2 3]
E = [1 2 3]
I want to create a matrix Z of size 3 x 5 from these vectors.
for loops are generally a bad idea in Matlab. Use vectorized syntax:
Z = [A;B;C;D;E]'; %'// vertical concatenation (5x3), then transpose to get 3x5
>> size(Z)
ans =
3 5
You can also transpose the vectors first and then concatenate them:
Z = [A' B' C' D' E']; %'// this comment is a syntax highlighting hotfix
>> size(Z)
ans =
3 5
If you really insist on using a for loop, here's how you would do that:
Z(3,5) = 0; %// preallocate a 3x5 numerical matrix
for i=1:3
Z(i,1) = A(i);
Z(i,2) = B(i);
Z(i,3) = C(i);
Z(i,4) = D(i);
Z(i,5) = E(i);
end
But it really makes no sense at all to do it this way...

MATLAB: 2-D array of structs (containing vectors) to 3-D Array?

I have a 2-dimensional array of structs 'cell' which each contain a number of vectors:
cell(1,1).U = [1 2 3];
cell(1,2).U = [4 5 6];
cell(2,1).U = [7 8 9];
cell(2,2).U = [0 1 2];
I would like to extract the data into a 3-D array A(i,j,k).
Using cell-style extraction returns a 1x3 cell, the contents of which are
>> {cell.U}
ans = {[cell(1,1).U] [cell(1,2).U] [cell(2,1).U] [cell(2,2).U]}
And thus, converting this to a matrix using cell2mat(), as in:
cell2mat(ans)
Returns a 3x4 array.
Ideally, I would like a 2x2x3 array so that the indices i and j are preserved. Is there any way (short of looping) to accomplish this?
Use CAT and RESHAPE. Also, don't call your variable cell, since that's a built-in function.
>> c(1,1).U = [1 2 3];
c(1,2).U = [4 5 6];
c(2,1).U = [7 8 9];
c(2,2).U = [0 1 2];
>> out = cat(1,c.U)
>> out = reshape(out,2,2,3)
out(:,:,1) =
1 4
7 0
out(:,:,2) =
2 5
8 1
out(:,:,3) =
3 6
9 2

Element-wise array replication in Matlab

Let's say I have a one-dimensional array:
a = [1, 2, 3];
Is there a built-in Matlab function that takes an array and an integer n and replicates each
element of the array n times?
For example calling replicate(a, 3) should return [1,1,1,2,2,2,3,3,3].
Note that this is not at all the same as repmat. I can certainly implement replicate by doing repmat on each element and concatenating the result, but I am wondering if there is a built in function that is more efficient.
I'm a fan of the KRON function:
>> a = 1:3;
>> N = 3;
>> b = kron(a,ones(1,N))
b =
1 1 1 2 2 2 3 3 3
You can also look at this related question (which dealt with replicating elements of 2-D matrices) to see some of the other solutions involving matrix indexing. Here's one such solution (inspired by Edric's answer):
>> b = a(ceil((1:N*numel(a))/N))
b =
1 1 1 2 2 2 3 3 3
a = [1 2 3];
N = 3;
b = reshape(repmat(a,N,1), 1, [])
As of R2015a, there is a built-in and documented function to do this, repelem:
repelem Replicate elements of an array.
W = repelem(V,N), with vector V and scalar N, creates a vector W where each element of V is repeated N times.
The second argument can also be a vector of the same length as V to specify the number of replications for each element. For 2D replication:
B = repelem(A,N1,N2)
No need for kron or other tricks anymore!
UPDATE: For a performance comparison with other speedy methods, please see the Q&A Repeat copies of array elements: Run-length decoding in MATLAB.
>> n=3;
>> a(floor((0:size(a,2)*n-1)/n)+1)
ans =
1 1 1 2 2 2 3 3 3
Some exotic alternatives. Admittedly more funny than useful:
Assign the (first) result of meshgrid to a vector:
b = NaN(1,numel(a)*n); %// pre-shape result
b(:) = meshgrid(a,1:n);
Build a matrix that multiplied by a gives the result:
b = a * fliplr(sortrows(repmat(eye(numel(a)),n,1))).';
Use ind2sub to generate the indices:
[~, ind] = ind2sub([n 1],1:numel(a)*n);
b = a(ind);
If you have the image processing toolbox, there is another alternative:
N = 3;
imresize(a, [1 N*numel(a)],'nearest')
% To get b = [1 1 1 2 2 2 3 3 3]
N = 3;
a = [1 2 3];
temp_a = a(ones(N,1),:);
b = reshape(temp_a,1,numel(temp_a));
% To get b = [1 2 3 1 2 3 1 2 3]
N = 3;
a = [1 2 3];
temp_a = a(ones(N,1),:);
b = reshape(temp_a',1,numel(temp_a));

Resources