Concatenate certain elements from a cell array into a numeric array - MATLAB - 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{:}]).'

Related

Push array onto 2D array (matrix) in 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

How to create vector of binary values based on correspondence between two other vectors in MATLAB [duplicate]

I'm developing a program with MatLab that calculates powers of numbers, adds them together, and then sees if any of the first set of numbers (numbers to powers) equals any of the added numbers to powers. I'm trying to check this for each value in the first array, however, I am getting an output like this:
m =
1
128
2187
16384
78125
279936
823543
2097152
4782969
10000000
for each m value, which is just the result of a simple for loop of the array. So when I go to check if m is in the array, it checks is [1, 128,2187,16384,78125...] in the array, and the answer is no. How can I get it to evaluate each individual entry, like this:
Array n is [1,128,2187,16384]
for m = n
m = 1
Is m in array? No
m = 128
Is m in array? No
m = 2187
Is m in array? Yes
m = 16384
Is m in array? No
end
My code is below:
C = [];
D = [];
E = [];
F = [];
numbers1 = [];
numbers2 = [];
numbers = 10;
powers = 10;
for i = 1:numbers
for j = 3:powers
C = [C;i^j];
end
C = transpose(C);
D = [D;C];
C = [];
end
[~,b] = unique(D(:,1)); % indices to unique values in first column of D
D(b,:); % values at these rows
for i = D
for a = D
E = [E;i+a];
end
E = transpose(E);
F = [F;E];
E = [];
end
[~,b] = unique(F(:,1)); % indices to unique values in first column of F
F(b,:); % values at these rows
for m = D % this is the for loop mentioned above
m
end
Example vectors:
>> m = [1 3 5 9];
n = [5 2 1 4 8];
To check if each element of vector m is in n, use ismember:
>>ismember(m,n)
ans =
1 0 1 0
To get the values, not the indices: use logical indexing on m:
>> m(ismember(m,n))
ans =
1 5
or directly use intersect:
>> intersect(m,n)
ans =
1 5

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

producing cell array

I want to produce a cell array as below in matlab:
P= {100;010;000;000;001}
{100;000;010;000;001}
{100;000;000;010;001}
{000;100;010;000;001}
{000;100;000;010;001}
{000;000;100;010;001}
where P= {5x3 cell} {5x3 cell} {5x3 cell} {5x3 cell} {5x3 cell} {5x3 cell};
from the 5x3 matrix, the pattern should be only one '1' in each column and the third column is '1' at final row in every cell.
i.e : P{1}= 100;010;000;000;001
how should I do that?
From what I had made up till now:
PP=zeros(5,3);
P={1,6};
P={PP,PP,PP,PP,PP,PP};
how can I put the ones in the cell?
thank you so much
Try this:
x = unique(perms([0 0 2 4]),'rows'); %# we'll convert 2 to 10 and 4 to 100 later
xi = randperm(size(x,1)); %# permute rows randomly
n = 6;
xi = xi(1:n); %# k random rows
x = x(xi,:);
x = [ x ones(n,1) ]'; %# add 1s and transpose
%# convert to strings representing binary numbers, then to cell array
out = reshape(cellstr(dec2bin(x)), size(x,1), n);
%# split the cell array by columns
out = mat2cell(out, size(out,1), ones(1,n));
If you actually need numbers (0, 10, 100), not strings, the code will be a little shorter:
x = unique(perms([0 0 10 100]),'rows');
xi = randperm(size(x,1));
n = 6;
xi = xi(1:n);
x = x(xi,:);
x = [x ones(n,1)]';
out = mat2cell(x,size(x,1),ones(1,n));
UPDATE:
According your comment, here is the new code:
n = 6;
P = repmat({zeros(5,3)},1,n); %# output array preallocation
x = unique(perms([0 0 1 2]),'rows');
xi = randperm(size(x,1));
xi = xi(1:n);
x = x(xi,:);
c = [x ones(n,1)+2]'; %# column index
r = repmat((1:5)',1,n); %# row index
for k=1:n
P{k}(sub2ind( [5 3], r(c(:,k)>0,k), c(c(:,k)>0,k) )) = 1;
end
If you need the array of logical matrices just substitute zeros with false in the 2nd line:
P = repmat({false(5,3)},1,n);

How can I convert a vector to a cell array?

I have a column vector I want to convert to a cell array such as:
A = rand(10,1);
B = cell(10,1);
for i=1:10
B{i} = A(i);
end
B =
[0.6221]
[0.3510]
[0.5132]
[0.4018]
[0.0760]
[0.2399]
[0.1233]
[0.1839]
[0.2400]
[0.4173]
How can I do this without an explicit for loop?
I tried:
B{:} = A(:)
and
[B{:}] = deal(A)
with no luck...
Also if possible, how can I do the same thing for a matrix, i.e. have each element in a cell by itself?
Use the function num2cell:
B = num2cell(A);
Works with matrices too.