Rearange matlab struct - matlab

Lets have a struct defined like this:
s.a = [1, 11];
s.b = [2, 22];
How can I convert it to struct defined like this:
s(1).a = 1;
s(1).b = 2;
s(2).a = 11;
s(2).b = 22;
This need comes from textscan() function. I read large file using this function and then convert the result using cell2struct() function. In this case, however, each field contains whole column, so one has to address individual value by s.column_name(row_index). While I would prefer to do it by s(row_index).column_name.

This type of operation with a struct array does not usually result in pretty code, but here it goes:
s2 = cell2struct(num2cell(cell2mat(struct2cell(s))).', fieldnames(s), 2);
In general, indexing a struct array across its two "dimensions" (fields and array index) is problematic for this reason. Have you considered using a table instead? It allows both types of indexing in a natural way:
s = table; % initiallize as table
s.a = [1; 11]; % note: column vectors
s.b = [2; 22];
So now
>> s
s =
2×2 table
a b
__ __
1 2
11 22
>> s.a
ans =
1
11
>> s.a(2)
ans =
11
>> s(:, 'a') % note: gives a (sub)table
ans =
2×1 table
a
__
1
11
>> s{:, 'a'} % same as s.a
ans =
1
11
>> s{2, :}
ans =
11 22
>> s{2, 'a'} % same as s.a(2)
ans =
11

A possible simple solution would be the following:
fn = fieldnames(s);
for j = 1 : numel(fn)
for k = 1 : numel(s(1).(fn{j}))
s2(k).(fn{j}) = s.(fn{j})(k);
end
end

Related

Indexing/Accessing MATLAB nested structure

Hope, that I'm not creating a duplicate, but so far I didn't find the right answer for my problem.
Let's say, we have the following structure(s):
a(1).b = 1;
a(1).x.y = 2;
a(2).b = 3;
a(2).x.y = 4;
When I now try to get all values of b, I can do:
>> a(:).b
ans = 1
ans = 3
But how to this with the nested struct .x.y?
>> a(:).x.y
Expected one output from a curly brace or dot indexing expression, but there were 2 results.
Thanks for your help...!
Just loop over the indices.
>> arrayfun(#(k) a(k).x.y, 1:numel(a))
ans =
2 4
or:
>> struct2array(cell2mat(extractfield(a,'x')))
ans =
2 4

How can I turn Structure to n-dimensional matrix

I have 2 matrices.
First one is the names.
Names={'a','b','c'};
Second one is Numbers.
a=[1 3]; b=[4]; c=[2 4 5];
Then i have the structure names which is combination of names and numbers, and they are equal some random matrices with equal rows and columns.
For this case i have 6 combination (2*1*3) and it looks like =
a1.b4.c2=[7 8 9; 10 11 14];
a1.b4.c4=[2 4 5; 3 4 7];
a1.b4.c5=[3 2 11; 4 7 8];
a3.b4.c2=[1 1 1; 3 5 12];
a3.b4.c4=[2 7 9 ; 10 11 12];
a3.b4.c5=[4 2 7 ; 5 6 8];
I want to return this into n-dimensional matrix. In this case it is 5-dimensional which has to look like this;
(:,:,1,4,2)=[7 8 9; 10 11 14]; %%%% for a=1 b=4 c=2
(:,:,1,4,4)=[2 4 5; 3 4 7]; %%%% for a=1 b=4 c=4
(:,:,1,4,5)=[3 2 11; 4 7 8]; %%%% for a=1 b=4 c=5
(:,:,3,4,2)=[1 1 1; 3 5 12]; %%%% for a=3 b=4 c=2
(:,:,3,4,4)=[2 7 9 ; 10 11 12]; %%%% for a=3 b=4 c=4
(:,:,3,4,5)=[4 2 7 ; 5 6 8]; %%%% for a=3 b=4 c=5
I want to write a generalized code that helps me do this job for different numbers of names and numbers yet I couldnt do it. Hope you can help me! Thanks.
To get every combination of the possible numbers for each fields, use ndgrid.
[Numbers{1:3}] = ndgrid(a,b,c);
Having the numbered structures sitting in the workspace as you describe makes it messy to access them programmatically and you should avoid it if possible; however they can still be accessed using eval.
evalPattern = strjoin(strcat(Names,'%d'), '.'); % 'a%d.b%d.c%d'
firstNumbers = cellfun(#(n) n(1), Numbers); % [1 4 2]
firstElement = eval(sprintf(evalPattern,firstNumbers)); % returns the value of a1.b4.c2
result = nan([size(firstElement) size(Numbers{1}]);
for ii = 1:numel(Numbers{1})
iiNumbers = cellfun(#(n) n(ii), Numbers);
result(:,:,ii) = eval(sprintf(evalPattern,iiNumbers));
end
Ok, it took longer than I expected, but the following code should work for arbitrary number of names and numbers, given the following requirements:
At the moment, names are considered to be single characters - that could be tweaked by regexp or something like this.
All your ax.bx.cx.... can be stored in some superordinated structure by your application (beforehand).
Your struct always follows the presented order of ax.bx.cx..., and the matrix dimensions are equal.
So, the script is quite long and - I'm afraid - needs some explanation. Please just ask. The basic idea is to loop through the struct(s) as long as the particular "children" are still structs. That assures arbitrary "depth" of structs, i.e. number of names and numbers.
I expanded your data, so you see, that it also works for (a) additional names, (b) additional numbers, and (c) different matrix sizes. Of course, it also works on your original data.
Also, one doesn't need Names or Numbers in the beginning as these information are automatically extracted from the (has to be there superordinated) structure.
(Attention: Written in Octave. I tried to verify, that all functionality is available in Matlab, too. Please report any issues, if that's not the case. I will then refactor the code.)
% Structs given.
a1.b4.c2.d3 = ones(4, 4);
a1.b4.c4.d3 = ones(4, 4) * 2;
a1.b4.c5.d3 = ones(4, 4) * 3;
a1.b6.c2.d3 = ones(4, 4) * 4;
a1.b6.c4.d3 = ones(4, 4) * 5;
a1.b6.c5.d3 = ones(4, 4) * 6;
a2.b4.c2.d3 = ones(4, 4) * 7;
a2.b4.c4.d3 = ones(4, 4) * 8;
a2.b4.c5.d3 = ones(4, 4) * 9;
a2.b6.c2.d3 = ones(4, 4) * 10;
a2.b6.c4.d3 = ones(4, 4) * 11;
a2.b6.c5.d3 = ones(4, 4) * 12;
% REQUIREMENT: Store your structs in some superordinated struct.
super.a1 = a1;
super.a2 = a2;
% Initialize combined struct for names and numbers.
NamesNumbers = struct();
% Initialize Names cell array.
Names = {};
% Extract names and numbers from superordinated struct.
totalNames = 0;
totalNumbers = 1;
current = super;
while (isstruct(current))
fields = fieldnames(current);
totalNames = totalNames + 1;
totalNumbers = totalNumbers * numel(fields);
for iField = 1:numel(fields)
field = fields{iField};
name = field(1);
Names{totalNames} = name;
number = field(2:end);
if (isfield(NamesNumbers, name) == false)
NamesNumbers.(name) = str2num(number);
else
NamesNumbers.(name) = [NamesNumbers.(name) str2num(number)];
end
end
current = current.(fields{1});
if (isstruct(current) == false)
[nRows, nCols] = size(current);
end
end
% Extract all values from superordinated struct.
level = struct2cell(super);
while (isstruct([level{:}]))
level = struct2cell([level{:}]);
end
values = vertcat(level{:});
% Determine indices.
maxIdx = cellfun(#(x) max(x), struct2cell(NamesNumbers));
idx = zeros([totalNumbers, totalNames]);
factorProd = 1;
for iName = 1:totalNames
numbers = NamesNumbers.(Names{iName});
n = numel(numbers);
factorProd = factorProd * n;
inner = totalNumbers / factorProd;
resh = totalNumbers * n / factorProd;
outer = factorProd / n;
column = repmat(reshape(repmat(numbers, inner, 1), resh, 1), outer, 1);
START = (iName - 1) * totalNumbers + 1;
STOP = iName * totalNumbers;
idx(START:STOP) = column;
end
% Initialize output.
output = zeros([nRows nCols maxIdx']);
% Fill output with values.
for iIdx = 1:size(idx, 1)
temp = num2cell(idx(iIdx, :));
START = (iIdx - 1) * nRows + 1;
STOP = iIdx * nRows;
output(:, :, temp{:}) = values(START:STOP, :);
end

Using accumarray and #min to extract min from groups but also output corresponding values from another variable/column

I have 3 columns of data:
time = [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16];
category = [1;1;1;1;2;2;2;2;3; 3; 3; 3; 4; 4; 4; 4];
data = [1;1;0;1;2;2;1;2;3; 3; 2; 3; 4; 4; 4; 3];
I am using the following to extract the minimum data values for each category:
groupmin = accumarray(category,data,[],#min)
Which outputs:
groupmin = [0;1;2;3]
However, I would really like to have an output that also tells me which time point the minimums are from, e.g.
timeofgroupmin = [3;7;11;16]
groupmin = [0;1; 2; 3]
Alternatively, I would like to have the minimums output in a vector of their own, with NaNs for any row which was not the minimum of its group, e.g.
groupminallrows = [NaN;NaN;0;NaN;NaN;NaN;1;NaN;NaN;NaN;2;NaN;NaN;NaN;NaN;3];
Either approach would solve my problem. As a Matlab novice I'm struggling to know which terms to search for.
This works if all data of the same category are in a single run and the categories are sorted, as in your example. Several minimizers are allowed within each category.
r = accumarray(category,data,[],#(v) {(min(v)==v)});
r = vertcat(r{:});
groupminallrows = NaN(size(data));
groupminallrows(r) = data(r);
Try this solution:
% first we group the data into cell according to the group they belong to
grouped = accumarray(category, data, [], #(x){x});
% find the minimum and corresponding index of each group
[mn,idx] = cellfun(#min, grouped);
% fix index by offsetting the position to point the whole data vector
offset = cumsum([0;cellfun(#numel, grouped)]);
idx = idx + offset(1:end-1);
% result
[mn(:) idx(:)]
assert(isequal(mn, data(idx)))
% build the vector with NaNs
mnAll = nan(size(data));
mnAll(idx) = mn;
The resulting vectors:
>> mn'
ans =
0 1 2 3
>> idx'
ans =
3 7 11 16
>> mnAll'
ans =
NaN NaN 0 NaN NaN NaN 1 NaN NaN NaN 2 NaN NaN NaN NaN 3
EDIT:
Here is an alternate solution:
% find the position of min value in each category
idx = accumarray(category, data, [], #minarg);
% fix position in terms of the whole vector
offset = cumsum([0;accumarray(category,1)]);
idx = idx + offset(1:end-1);
% corresponding min values
mn = data(idx);
I'm using the following custom function to extract the second output argument from min:
minarg.m
function idx = minarg(X)
[~,idx] = min(X);
end
The results are the same as above.
Use accumarray with a custom function:
time = [1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16];
category = [1;1;1;1;2;2;2;2;3; 3; 3; 3; 4; 4; 4; 4];
data = [1;1;0;1;2;2;1;2;3; 3; 2; 3; 4; 4; 4; 3];
groupmin = accumarray( A(:,1), A(:,2), [], #min)
Is what you have, but to get the indices of the minima and their time you'd need the second output of the min function, which I don't know if it is possible to get when used with accumarray. But there is the following workaround:
groupidx = accumarray( category, data, [], #(x) find(x == min(x) )).'
occ = cumsum(hist(category,unique(category)))
idx = -occ(1)+occ+groupidx;
timeofgroupmin = time(idx).'
groupmin = data(idx).'
groupmin =
0 1 2 3
timeofgroupmin =
3 7 11 16
The desired NaN-vector you could get like:
groupminallrows = NaN(1,numel(data));
groupminallrows(idx) = data(idx)
Regarding your comment:
I assume the reason for that, is that you have multiple minima in each group, then find returns an array. To resolve that you can substitute find(x == min(x)) with find(x == min(x),1). But then you would just get the first occurance of every minimum in each group.
If that is not desired I'd say accumarray is generally the wrong way to go.

From struct to array

Let's say I have this structure:
Results(i,j).fo
Results(i,j).co
where i=19 and j=30. How can I save in a ixj matrix all Results(i,j).fo? Or even better, How can I say to bootci to read only Results(i,j).fo
Media_tot = mean(Matrix,2)
ci = bootci(1000, #mean, Matrix');
ci = abs(ci' - repmat(Media_tot,1,2));
hE = errorbar(xdata_m, ydata_m, ci(:,1), ci(:,2));
I think this should work for your first question:
reshape([Results.fo], 19, 30)
e.g.
%// Make a 3x3 matrix of structs with 2 fields
A = [];
for k = 1:9
A(k).x = k;
A(k).y = 9-k;
end
A= reshape(A,3,3)
Now
reshape([A.x], 3,3)
ans =
1 4 7
2 5 8
3 6 9
and
reshape([A.y], 3,3)
ans =
8 5 2
7 4 1
6 3 0
Given an array of equivalent structures, e.g.
Results = [ struct('fo',1, 'co',2) struct('fo',10, 'co',20); struct('fo',100, 'co',200) struct('fo',1000, 'co',2000) ]
You can access all 'fo` using the square brackets
all_fo = [Results.fo]
% >> [1 100 10 1000]
However, they are then in a 1D-array, to get them in the original format, use
all_fo = reshape([Results.fo], size(Results))
% >> [1 10; 100 1000]

Check for [] simulink

However I try to test if x is [] I fail, seems that it should be trivial, but can't figure out how to do it.
if I run x = rmi('get',subsystemPath);
ans = []
I've tried
x == []
x
isempty(fieldnames(x))
isEmpty(x)
but nothing works
function requirements = GetRequirementsFromSubsystem(subsystemPath)
x = rmi('get',subsystemPath);
if(isempty(fieldnames(x))) %%%%%%%%%%%%%%%%<------
requirements = 0;
else
requirements = {x.description}; % Fails if do this without a check
end
end
Any ideas?
x is a struct, right? In that case, according to this posting on the MATLAB newsgroup, there are two kinds of emptiness for structs:
S = struct() => no fields
isempty(S) is FALSE, because S is a [1 x 1] struct without fields
S = struct('Field1', {}) => fields, but no data
isempty(S) is TRUE, because S is a [0 x 0] struct with fields
For me, isempty(fieldnames(S)) works only for the first case in Octave, at least.
If x on the other hand, is an array, not a struct, then isempty(x) should work.
>> S = struct()
S =
scalar structure containing the fields:
>> isempty(S)
ans = 0
>> isempty(fieldnames(S))
ans = 1
>> S = struct('Field1',{})
S =
0x0 struct array containing the fields:
Field1
>> isempty(S)
ans = 1
>> isempty(fieldnames(S))
ans = 0
>> x = []
x = [](0x0)
>> isempty(x)
ans = 1