How to convert a struct to a matrix - matlab

I have a 10 x 10 struct with four fields a,b,c,d.
How do I convert this struct to a 10 x 10 matrix with entries only from the field a?

You can rely on the fact that str.a returns a comma-separated list. We can therefore concatenate the values together and reshape the resulting array to be the same size as the input struct.
% If a contains scalars
out = reshape([str.a], size(str));
% If a contains matrices
out = reshape({str.a}, size(str));

One liner solution
res = cellfun(#(strctObj) strctObj.a,str,'UniformOutput',false);
Further explanation
Define a one-line function which extract the a value.
getAFunc = #(strctObj) strctObj.a;
use MATLAB's cellfun function to apply it on your cell and extract the matrix:
res = cellfun(#(strctObj) getAFunc ,strctCellObj,'UniformOutput',false);
Example
%initializes input
N=10;
str = cell(N,N);
for t=1:N*N
str{t}.a = rand;
str{t}.b = rand;
str{t}.c = rand;
str{t}.d = rand;
end
%extracts output matrix
res = cellfun(#(strctObj) strctObj.a,str,'UniformOutput',false);

Related

operations with structure in matlab

I have a structure 1x300 called struct with 3 fields but I'm using only the third field called way. This field is, for each 300 lines, a vertor of index.
Here an exemple with 3 lines to explain my problem : I woud like to search if the last index of the first line is present in an other vector (line) of the field way.
way
[491751 491750 491749 492772 493795 494819 495843 496867]
[491753 491754 491755 491756]
[492776 493800 494823 495847 496867]
I tried with intersect function :
Inter=intersect(struct(1).way(end), struct.way);
but Matlab returns me an error :
Error using intersect (line 80)
Too many input arguments.
Error in file2 (line 9)
Inter=intersect(struct(1).way(end), struct.way);
I don't understand why I have this error. Any explanations and/or other(s) solution(s)?
Let the data be defined as
st(1).way = [491751 491750 491749 492772 493795 494819 495843 496867];
st(2).way = [491753 491754 491755 491756];
st(3).way = [492776 493800 494823 495847 496867]; % define the data
sought = st(1).way(end);
If you want to know which vectors contain the desired value: pack all vectors into a cell array and pass that to cellfun with an anonymous function as follows:
ind = cellfun(#(x) ismember(sought, x), {st.way});
This gives:
ind =
1×3 logical array
1 0 1
If you want to know for each vector the indices of the matching: modify the anonymous function to output a cell with the indices:
ind = cellfun(#(x) {find(x==sought)}, {st.way});
or equivalently
ind = cellfun(#(x) find(x==sought), {st.way}, 'UniformOutput', false);
The result is:
ind =
1×3 cell array
[8] [1×0 double] [5]
Or, to exclude the reference vector:
n = 1; % index of vector whose final element is sought
ind = cellfun(#(x) {find(x==st(n).way(end))}, {st([1:n-1 n+1:end]).way});
You propbably want to use ismember.
Consider what you are passing to the intersect/ismember functions too, struct.way isn't a valid argument, you may need to loop to iterate over each line of your struct (in this case it would be easier to have a cell array, or matrix with equal length rows).
output = zeros(300);
for ii = 1:300
for jj = 1:300
if ii ~= jj && ismember(struct(ii).way(end), struct(jj).way)
output(ii,jj) = 1;
end
end
end
Now you have a matrix output where the elements which are 1 identify a match between the last element in way in the struct row ii and the vector struct(jj).way, where ii are the matrix row numbers and jj the column numbers.

Select an element of a Sub matrix

I have a Matrix of 100 sub matrix . Each of this sub matrix have 6 elements (1*6),
I need to compute the mean of the first element of each sub matrix then the
second, etc
Example:
B=[4,**3**,2,1,1,2]
C=[4,**3**,5,1,1,2]
D=[6,**3**,2,1,1,2]
A={B,C,D}
...etc
So I want the mean of the surlined numbers, then the next etc
How can I do that ???
Thanks by advance,
i think what you need here is the command cell2mat. here a small script of how to compute means automatically without knowing the size of the data. let me know if that was what you were looking for.
% Problem
vec1 = [4,3,2,1,1,2];
vec2 = [4,3,5,1,1,2];
vec3 = [6,3,2,1,1,2];
A = {vec1,vec2,vec3};
% get dimensions
cols = numel(cell2mat(A(1)));
rows = numel(A);
% convert list of vectors to matrix
M = cell2mat(A);
M = reshape(M,[cols,rows]);
M = M';
means = mean(M)

Random permutation of each cell in a cell array

I have a 1-by-4 cell array, D. Each of the cell elements contains 2-by-2 double matrices. I want to do random permutation over each matrix independently which in result I will have the same size cell array as D but its matrices' elements will be permuted and then the inverse in order to obtain the original D again.
for a single matrix case I have the code and it works well as follows:
A=rand(3,3)
p=randperm(numel(A));
A(:)=A(p)
[p1,ind]=sort(p);
A(:)=A(ind)
but it doesn't work for a cell array.
The simplest solution for you is to use a loop:
nd = numel(D);
D_permuted{1,nd} = [];
D_ind{1,nd} = [];
for d = 1:nd)
A=D{d};
p=randperm(numel(A));
A(:)=A(p)
[~,ind]=sort(p);
D_permuted{d} = A;
D_ind{d} = ind;
end
Assuming your D matrix is just a list of identically sized (e.g. 2-by-2) matrices, then you could avoid the loop by using a 3D double matrix instead of the cell-array.
For example if you hade a D like this:
n = 5;
D = repmat([1,3;2,4],1,1,n)*10 %// Example data
Then you can do the permutation like this
m = 2*2; %// Here m is the product of the dimensions of each matrix you want to shuffle
[~,I] = sort(rand(m,n)); %// This is just a trick to get the equivalent of a vectorized form of randperm as unfortunately randperm only accepts scalars
idx = reshape(I,2,2,n);
D_shuffled = D(idx);

Dynamically create numeric matrix from fields of a scalar structure

in Matlab, I have a scalar structure S with some fields. Each field contains a numeric vector, and all these vectors have the same size, say nx1.
Now I would like to create a numeric matrix based on a selection of the fields.
The starting point is a logical mask sized mx1, where m is the number of fields of S. mask(i) is true if the ith field of S should be included in the matrix. So the matrix size would be n x sum(mask).
Example (in my code, the structure is not built in this way, of course :-)
vec = rand(1000,1);
S.f1 = vec;
S.f2 = vec;
S.f3 = vec;
S.f4 = vec;
S.f5 = vec;
mask = [false true true false false]; % 5 elements because S has 5 fields
The expected output would be:
output = [S.f2 S.f3];
But of course, the creation of output should depend dynamically on the fields of S and on mask.
Is there any way to achieve this without using an ugly construction including a filter of the struct field names, loop, etc.?
Thank you very much!
Philip
Here's one way -
fns = fieldnames(S) %// Get all fieldnames
S = rmfield(S,fns(~mask)) %// Remove all fields with masking values as false
Next, to get your numeric array, use struct2array -
output = struct2array(S)
You can convert the struct into a cell using struct2cell, and use normal cell indexing to get the fields you want.
a = (1:5).';
s.f1 = a; s.f2 = 2*a; s.f3 = 3*a; s.f4 = 4*a; s.f5 = 5*a;
c = struct2cell(S);
[c{mask}]
ans =
2 3
4 6
6 9
8 12
10 15
You can do something like:
msks = fieldnames(S);
msks = msks(mask);
n = numel(msks);
output = zeros(1000,n);
for i = 1:n
output(:,i) = S.(msks{i});
end

Matlab: Create a matrix from a row vector according to specifications

I am working in matlab. I have a row vector in and a scalar number fuzzy_no. I want to create a matrix output of size fuzzy_no x (numel(in)-fuzzy_no). such that the ith col of the matrix output has the elements from i:i+fuzzy_no-1 of row vector in.
In other words I want to implement the following loop without using loops
n = numel(in);
output = zeros(fuzzy_no,n-fuzzy_no);
for i = 1:size(output,2)
output(:,i) = in(1,i:i+fuzzy_no-1);
end
Note that in your example the last element from in is missing in the output. Assuming you want all the elements, you could use indexing like so:
[ii, jj] = meshgrid(1:fuzzy_no, 0:n-fuzzy_no);
output = in(ii+jj)
Or you could use the slightly more satisfying hankel built-in:
output = hankel(in(1:fuzzy_no), in(fuzzy_no:end))
Try this -
n = numel(in);
lim1 = n-fuzzy_no
t1 = bsxfun(#times,in',ones(1,lim1)) %//'
uind = triu(ones(size(t1)),1)>0
lind = [zeros(fuzzy_no,lim1) ; tril(ones([size(t1,1)-fuzzy_no lim1]))]>0
t1(uind | lind)=[];
output = reshape(t1,fuzzy_no,n-fuzzy_no)