Push array onto 2D array (matrix) in MATLAB - matlab

For God only knows what reason, we're being asked to use MATLAB in an AI course. All I want to do is initialize an array, and push arrays onto it. In Ruby, this would be:
multi_arr = []
an_arr = [1, 2, 3, 4]
multi_arr << an_arr
Done! Unfortunately I can't find a similarly simple solution in MATLAB.
Any advice would be extremely appreciated.
EDIT: for the interested, here's the rather ungraceful solution I arrived at:
child_states = []
child_state = [0,1,2,3,4,5,6,7,8]
% returns [rows, columns]
dimensions = size(child_states)
child_states(dimensions(1)+1, 1:9) = child_state

You can append array to an array in matlab without knowing the dimensions but it won't be very efficient because matlab will allocate space for the whole array each time you do it. Here's how to do it:
arrays = [];
arr1 = [1,2];
arr2 = [3,4,5];
% append first array
arrays = [arrays ,arr1 ]
% append second array
arrays = [arrays ,arr2 ]
arrays =
1 2
arrays =
1 2 3 4 5
if each of the arrays you want to append have the same length, then you can append them as rows:
arrays = [];
arr1 = [1,2,4];
arr2 = [5,6,7];
% append first array
arrays = [arrays ; arr1 ]
% append second array
arrays = [arrays ; arr2 ]
arrays =
1 2 4
arrays =
1 2 4
5 6 7
for more of a ruby like array appending you should use cell arrays:
cells = {};
cells = [cells ,[4,5] ]
cells = [cells ,[1,1,1] ]
cells = [cells ,['hello']]
cells =
[1x2 double] [1x3 double] 'hello'

GIYF. It seems that you are looking for horzcat and vertcat. Check out MATLAB's doc at Creating and concatenating matrices.; from vertcat page:
C = vertcat(A1,...,AN) vertically concatenates arrays A1,...,AN. All arrays in the argument list must have the same number of columns.
If the inputs are multidimensional arrays, vertcat concatenates N-dimensional arrays along the first dimension. The remaining dimensions must match.

Here's a function that's supposed to do what you want: concatenate a row vector to an array regardless of size. This function will check the dimension along the second axis of input and output array and pad zero to whichever one that is smaller so they can be concatenated along the first axis.
function m = freevertcat(m, n)
if isempty(m)
m = cat(1, m, n);
else
size_m = size(m, 2);
size_n = size(n, 2);
if size_m > size_n
n(size_n+1 : size_n + size_m - size_n) = 0
elseif size_n > size_m
m(:, size_m+1 : size_m + size_n - size_m) = 0;
end
m = cat(1, m, n);
end
example usage
m = []
n = [1,2,3,4,5]
m = freevertcat(m,n)
p = [3,3,3]
m = freevertcat(m,p)
You'll get
m = 1 2 3 4 5
3 3 3 0 0

Related

How to get all unique values in a cell array of matrices?

I want to get all unique values in A, where A is a cell array of matrices of different shapes and sizes:
A = {[], 1, [2 3], [4 5; 6 7]};
U = [];
for ii = 1: numel(A)
a = A{ii};
U = [U; a(:)];
end
U = unique(U);
That returns:
U =
1 2 3 4 5 6 7
If all elements in A where row vectors, I could use [A{:}] like:
U = unique([A{1:3}]);
That returns:
U =
1 2 3
But in my case it throws an exception:
Error using horzcat
Dimensions of matrices being concatenated are not
consistent.
So how can I avoid that for-loop?
You can use cellfun to reshape all elements in the cell.
U = unique(cell2mat(cellfun(#(x)reshape(x,1,numel(x)),A, 'UniformOutput', false)));
or avoiding the reshapewith
U = unique(cell2mat(cellfun(#(x)x(:).',A, 'UniformOutput', false)));
We can go this way:
A = {[], 1, [2 3], [2 0; 4 5; 6 7]};
AA = cellfun( #(x) unique(x(:)), A, 'UniformOutput' , false)
res = unique(cat(1, AA{:}))
First of all create unique array for each cell - it let us avoid converting all the cells to numeric just only unique values.
Lets convert cell array to one numeric array - cat(1, AA{:}) .
Find unique values through this resulting array.

Concatenate certain elements from a cell array into a numeric array - MATLAB

I have a nested cell array A, for example A is 1 x 6 cell.
Each cell of A contains another array of cells (for ex. A{1} = 1 x n cell).
Each cell of A{1}{1} contains other cell arrays A{1}{1} = 1 x n cell
I would like to list the content of the cell in a unique array.
A = cell(1,2);
A{1} = cell(1,2);
A{2} = cell(1,1);
A{1}{1} = [{1} {2}];
A{1}{2} = [{3} {4}];
A{2}{1} = [{5} {6}];
vec = [];
for i = 1 : size(A,2)
for j = 1 : size(A{1,i},2)
vec = [vec; cell2mat(A{1,i}{1,j}(:,2))];
end
end
vec = [2;4;6]
Is there a way to avoid the for loop?
Thanks
See is this works for you -
A_horzcat = horzcat(A{:})
out = cell2mat(vertcat(A_horzcat{:}))
vec = out(:,2)
Another approach (a one-liner! and I like it better) -
vec = arrayfun(#(x) x{1}{2}, [A{:}]).'

Array from vector on the basis of a second array

I have a vector v. I need to form an array a containing elements specified according to another array b. Each row in a (let's denote it by r) should contain all elements from v, with starting and ending indices corresponding to the first and last elements given in the matching column in b. For instance:
A(1, :) = v(b(1, 1):b(2, 1));
A(2, :) = v(b(1, 2):b(2, 2));
A(3, :) = v(b(1, 3):b(2, 3));
and so on. Obviously b(2,:) = b(1,:) + constant.
Can I do this without a loop in MATLAB?
Try this:
N=8; P=3; M=5;
v = rand(N,1);
b = zeros(2,M);
b(1,:) = [1 2 4 5 6];
b(2,:) = b(1,:) + P - 1;
A = cell2mat(arrayfun(#(i0,i1) v(i0:i1),b(1,:),b(2,:),'UniformOutput',false))'
You can use linear indexing and bsxfun to directly access the elements:
A = v(bsxfun(#plus, b(1,:).', 0:b(2,1)-b(1,1)));

Octave appending in a 2D cell array

I'm trying to append an element at the end of a 2D cell array row. My code is:
b = cell(5, 0)
b(1) = {b(1, :), 2} % Trying to append at the end of the first row
This gives me the error: error: A(I) = X: X must have the same size as I
I've also tried various other forms, such as:
b = cell(5, 0)
b(1, end+1) = 2 % Ok, inserts 2 at [1,1]
b(2, end+1) = 3 % No, inserts 3 at [2,2] instead of [2, 1]
It seems that you are confused with cell array indexing.
If you want to append elements at the end of a row in a matrix (in your case, a cell array), you must still make sure that all rows are of the same size after the assignment, otherwise you'll trigger an error about mismatching dimensions.
Instead of b(1) = {b(1, :), 2}, the following should work:
b(1, end + 1) = 2
Alternatively, if you want to append an entire column array of cells to b, use horizontal concatenation, for example:
b = [b, {2; 3; 4; 5; 6}];
This should append a single cell at the end of each row of b.
The reason the element gets inserted at [2, 2] and not [1, 1] is that by the time you try to insert the second element, the value denoted by end has increased from 0 to 1.
The following should do what you need:
>> b = cell(5, 0)
b =
Empty cell array: 5-by-0
>> b(1,1) = {2}
b =
[2]
[]
[]
[]
[]
>> b(2,1) = {3}
b =
[2]
[3]
[]
[]
[]
>>

Multiplying Cell with elements of a matrix Matlab

I have a 1xm cell array A{}, with each element of the array being NxN matrix and a matrix W(N1,m).
I need to calculate
Sum(j) = W(j,1)*A{1,1} + W(j,2)*A{1,2}
and I am doing the following:
for j=1:N1
sum=false(N);
for k=1:m
sum = sum + W(j,k)*A{1,k};
end
Sum(j)=sum
end
Or more visually :
Matrix W(let's say N1=2)
|W11 W12||A{1,1}| = |W11*A{1,1} + W12*A{1,2}|
|W21 W22||A{1,2}| = |W21*A{1,1} + W22*A{1,2}|
Is there a way of doing it without using the loops?
To do that without for-loops, you can rape (pardon the expression) the arrayfun command:
w_func = #(j)arrayfun(#(k)(W(j, k) * A{k}), 1:m, 'Un', 0)
sum_func = #(x)sum(cat(3, x{:}), 3)
S = arrayfun(#(j)sum_func(w_func(j)), 1:N1, 'Un', 0);
This produces a cell array S that contains all the sums, from S{1} to S{N1}.
I'm confused over what you are trying to do, but if I understand it correctly, this code should work:
temp = cell2mat(A);
a_sum = temp*repmat(eye(n),m,1); % this reduces A by performing sum like operation so [1 1 1 3;0 1 0 2]
% becomes [2 4; 0 3]
Sum = W * a_sum
I am also not sure I understood the question, but here is some code to consider:
%# create some data resembling what you described
N = 2;
m = 4;
N1 = 5;
W = rand(N1,m);
A = cell(1,m); for i=1:m, A{i} = rand(N); end
%# do the multiplications
s = cell(N1,1);
for j=1:N1
AA = cellfun(#times, A, num2cell(W(j,:)), 'UniformOutput',false);
s{j} = sum(cat(3,AA{:}), 3);
end
The cell array s now contains the result such that:
s{j} = W(j,1)*A{1} + W(j,2)*A{2} + ... + W(j,m)*A{m}
thus s is a cell array of size N1-by-1, where each cell contains an N-by-N matrix