Removing Structures - matlab

I am programming a GUI and I have a variable structure like:
bin: 0.2000
Logical1: 0
Logical2: 0
Matrixraw: {[1x1 struct] [1x1 struct]}
Matrixfiltered: {[1x1 struct] [1x1 struct]}
Matrixcorrected: {[1x1 struct] [1x1 struct]}
Every input file has its own matrix. In this case, we have two input files because every Matrix has two sructures. If we put 3 input files would be 3 structures and so on.
I want to make a button that given one index 1,2,3.. erases the i'th component from the Matrix structure. So, if you type 2 it will erase the second component of the matrix and would give:
bin: 0.2000
Logical1: 0
Logical2: 0
Matrixraw: {[1x1 struct]}
Matrixfiltered: {[1x1 struct]}
Matrixcorrected: {[1x1 struct]}
Thanks.

If you want to delete a member of structure:
Matrixraw = struct('field1', 1, 'field2', '2')
Matrixraw =
field1: 1
field2: 2
// delete first element of structure
Matrixraw(1) = []
Matrixraw =
field1: []
field2: []
The syntax below will empty the structure and remove completely your variable data:
// both works
Matrixraw = {}
Matrixraw = []

Here is a simple way to do it.
Suppose you have this:
Matrixfiltered= {[1 2], {}, 4}
and now we want to remove the second one:
Matrixfiltered(2) = []
Now you have this:
Matrixfiltered= {[1 2], 4}
Just give it a try!

Related

How to generate every possible permutation of a MATLAB structure

I have a MATLAB template structure that I'm using as a basis for a more complex output structure
conditions = {'Listen',':=:'};
items = ["apple" "duck"]; % 2 items
stims = cellstr([ ...
items, ... % text
items+".PNG", ... % picture
items+".wav" ... % sound
]);
event = struct( ...
'Cue', struct('duration',2,'jitter',0.25,'shows',conditions), ...
'Stimuli', struct('duration','sound','shows',stims), ...
'Delay', struct('duration',2,'jitter',0.25), ...
'Go', struct('duration',1,'jitter',0.25,'shows','Speak','skip','Cue==:=:'), ...
'Response', struct('duration',3,'jitter',0.25,'skip','Cue==:=:'));
events output is a 1×1 struct with the fields:
events =
1×1 struct with fields:
Cue: [1×2 struct]
Stimuli: [1×6 struct]
Delay: [1×1 struct]
Go: [1×1 struct]
Response: [1×1 struct]
I want to generate from this a 1×12 struct that contains each of the possible combinations of each top level field. Like below:
events =
1×12 struct array with fields:
Cue: [1×1 struct]
Stimuli: [1×1 struct]
Delay: [1×1 struct]
Go: [1×1 struct]
Response: [1×1 struct]
Edit: I should add that I want the output to dynamically reflect changes in the input. For example:
If the user decides to change event.Delay.duration = [1,2,3] it would generate a struct array three times the original size, with each possible delay duration implemented
If the user decides to remove the Cue field entirely, the output should be a struct array half the original size.
That should do the trick:
eC = struct2cell( event );
eN = fieldnames( event );
nums = cellfun( #numel, eC );
subs = cell( numel(nums), 1);
event = cell( prod(nums) , 1);
for k = 1 : prod(nums)
[ subs{:} ] = ind2sub( nums, k );
event{k} = cell2struct( cellfun(#(X,Y) X(Y), eC, subs, 'UniformOutput', false ), eN', 1 );
end
event = cat( 1, event{:} )';
Key point is the ind2sub function, which is in general helpful when dealing with multi-dimensional problems. Breaking them down to one dimension hast two advantages: 1) Nested loops are not needed. 2) We get independent from the number of dimensions.

Iterating over Matlab struct

I have a 1x1 Matlab struct with 15 fields
results =
RAR_no_compartments_2_0: [1x1 struct]
RAR_no_compartments_2_1: [1x1 struct]
RAR_no_compartments_2_10: [1x1 struct]
RAR_no_compartments_2_11: [1x1 struct]
RAR_no_compartments_2_12: [1x1 struct]
RAR_no_compartments_2_13: [1x1 struct]
RAR_no_compartments_2_14: [1x1 struct]
RAR_no_compartments_2_2: [1x1 struct]
RAR_no_compartments_2_3: [1x1 struct]
RAR_no_compartments_2_4: [1x1 struct]
RAR_no_compartments_2_5: [1x1 struct]
RAR_no_compartments_2_6: [1x1 struct]
RAR_no_compartments_2_7: [1x1 struct]
RAR_no_compartments_2_8: [1x1 struct]
RAR_no_compartments_2_9: [1x1 struct]
I'm trying to cycle through each of these in a for loop:
model_names=fieldnames(results); %get the names of each sub-struct
fieldname_dims=size(fieldnames(results)); %get dimensions of each struct
for i=1:fieldname_dims(1), %iterate over number of substructs
name=model_names(i) %get the model name
results.(name) %access the substruct
end
However Matlab returns the following error:
Argument to dynamic structure reference must evaluate to a valid field name.
Could somebody please explain to me why this is an invalid field name?
This is precisely what structfun is made for. It allows you to loop through all the fields of a structure.
a = struct('a', 1, 'b', 2, 'c', 3);
structfun(#(x)disp(x), a)
1
2
3
Alternately, you may consider storing an array of structures rather than a structure where the fields have numbers in them like you have. Any time that you are reliant on a fieldname to know ordering, it may be better to use a different data structure.
For in your data, rather than having a fieldname of RAR_no_compartments_2_0 you'd simply assign the struct assigned to that field by index
RAR_no_compartments(1) = results.RAR_no_compartments_2_0;
RAR_no_compartments(2) = results.RAR_no_compartments_2_1;
...
This way, rather than a 1 x 1 struct with 15 fields, you'd have a 1 x 15 array of structs which is much easier to deal with natively within MATLAB.
Just a thought.
The problem is that fieldnames returns a cell array, so you have to use curly brackets to access the content of a cell. This should work:
model_names=fieldnames(results);
fieldname_dims=size(fieldnames(results),1);
for i=1:fieldname_dims
name=model_names{i};
results.(name)
end
The whole thing can be simplified by actually iterating over the cell array instead of using a counter and temporary variables:
for name = fieldnames(results).'
results.(name{:}) % do whatever with your field
end
However, the correct way to access all fields of a struct is structfun—see Suever's answer.

Using Cell Array Contents to Create Struct Entries

Say that I have two cell arrays, A and B, that contain string values. I wish to populate a struct S such I generate every possible combination of S.valueinA.valueinB = 1. I am currently trying to accomplish this with two nested for-loops that iterate through every possible combination and wanted to ask if there is a more efficient way to solve this problem in MATLAB.
If you want to make dynamic field names in structures, I don't see how else you can do it without two for loops. Let's say we have two cell arrays A and B that consist of string entries.
For my example, apologies for the strings inside these arrays in advance as I couldn't think of anything better at the moment!
Is this what you're trying to achieve?
S = struct();
A = {'hello', 'my', 'name', 'is', 'ray'};
B = {'i', 'am', 'doing', 'awesome'};
for idx = 1 : numel(A)
for idx2 = 1 : numel(B)
S.(A{idx}).(B{idx2}) = 1;
end
end
This creates a nested structure S such that for each element in A, this becomes a field in S where this field is another structure that contains fields with names coming from all elements in B.
If we displayed S, we get:
>> S
S =
hello: [1x1 struct]
my: [1x1 struct]
name: [1x1 struct]
is: [1x1 struct]
ray: [1x1 struct]
If we accessed the hello field of S, we get:
>> S.hello
ans =
i: 1
am: 1
doing: 1
awesome: 1
Similarly, if we accessed the my field, we get:
>> S.my
ans =
i: 1
am: 1
doing: 1
awesome: 1
Therefore, if we want to get the hello field followed by the am field, we do:
>> S.hello.am
ans =
1

How can I group variables from a mat file by name and collect them in a structure?

I'm reading in a mat file which has variables with a counter e.g. a1, a2, a3, b, c1 and c2.
I want to put the data into a structure with field names "a", "b" and "c" where
a=[a1;a2;a3], b=b and c = [c1; c2].
The algorithm needs to be able to do this, without knowing what the maximum value of the counter of each variable is. How can I do this?
First, you would load your mat file data using the load function, placing it in a structure. Let's say that gave you the following sample data:
>> s = struct('a1',1:5,'b',[],'a2',1:5,'a3',1:5,'c1',1:3,'c2',3:5)
s =
a1: [1 2 3 4 5]
b: []
a2: [1 2 3 4 5]
a3: [1 2 3 4 5]
c1: [1 2 3]
c2: [3 4 5]
Then, we'll order the fields alphabetically using orderfields, find the field names using fieldnames, use regexprep to strip all trailing numbers off of the field names, then get the unique substrings using unique:
>> s = orderfields(s);
>> [strs, inds] = unique(regexprep(fieldnames(s), '\d*$', ''), 'last')
strs =
'a'
'b'
'c'
inds =
3
4
6
Using the indices returned by unique, we can calculate how many times each substring appears by doing diff([0; inds]). Then, we group the structure data into a cell array using these counts and struct2cell and mat2cell:
>> data = mat2cell(struct2cell(s), diff([0; inds]))
data =
{3x1 cell}
{1x1 cell}
{2x1 cell}
Notice that we have a cell array of cell arrays. If you know for sure that each set of entries for each substring will concatenate properly (as in our example), you can concatenate them using cellfun and cell2mat as follows:
>> data = cellfun(#cell2mat, data, 'UniformOutput', false)
data =
[3x5 double]
[]
[2x3 double]
Now we have a cell array of matrices, and a new structure can be made using cell2struct:
>> snew = cell2struct(data, strs)
snew =
a: [3x5 double]
b: []
c: [2x3 double]

Find Values in cell array of struct

I have two cell array's with structure in it.
example:
xmlFB =
Columns 1 through 5
[1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct]
xmllink =
Columns 1 through 3
[1x1 struct] [1x1 struct] [1x1 struct]
xmlFB{1}
ans =
Param: {[1x1 struct] [1x1 struct]}
InterChartConnection: [1x1 struct]
Tasks: [1x1 struct]
Attributes: [1x1 struct]
xmllink{1}
ans =
Attributes: [1x1 struct]
In "xmllink" there is the struct "Attributes" and in there is the Field "Name" with the Value "EN1"
And in xmlFB in the struct "Attributes" there are two Fields "Name" and "Typ"
The Names are unique.
What i want to do is to find the "Typ" in "xmlFB" from the names in the "xmllink".
First i wanted to do with a Loop, but the i read about these arrayfun/structfun/cellfun functions from Matlab.
Is there a way to do this with these? Or is a Loop better?
Let's assume that all variables in Names and Typ are strings. (Should work for scalars as well.)
Here is how to get the values into cell arrays and link them.
% create cell arrays
xmllinkname = cellfun(#(x) x.Attributes.Name, xmllink, 'UniformOutput',0);
xmlFBname = cellfun(#(x) x.Attributes.Name, xmlFB, 'UniformOutput',0);
xmlFBtyp = cellfun(#(x) x.Attributes.Typ, xmlFB, 'UniformOutput',0);
% match names
[idx1, idx2] = ismember(xmllinkname,xmlFBname);
idx2(idx2==0)=[]; % in case some names in xmllink absent in xmlFB
% get matched names and typ
xmllinknamematched = xmllinkname(idx1);
xmllinktyp = xmlFBtyp(idx2);
Since the order of values in the first cell arrays will be the same as in your original cell arrays of structures, you can use those indices idx1 and idx2 to match the structures as well.
xmllinkmatched = xmllink(idx1);
xmlFBmatched = xmlFB(idx2);
Of course, you can avoid creating the temporary arrays and put the first two cellfun statement into ismember statement.
Use the loop.
First things first: only start worrying about performance when it is actually a problem, and only after you get it right.
Now, if I understood you correctly, here are generally two ways to accomplish what you want:
% create some bogus data with the same structure
% ---------------------------
f_xmllink = #(N) struct(...
'Attributes', struct(...
'Name', num2str(N))...
);
f_xmlFB = #(N) struct(...
'Attributes', struct(...
'Name', num2str(N),...
'Typ' , num2str(N))...
);
% using numbers as names
xmllink = {
f_xmllink(190)
f_xmllink(331) % 2
f_xmllink(321) % 3
f_xmllink(239)
};
xmlFB = {
f_xmlFB(331) % 1
f_xmlFB(200)
f_xmlFB(108)
f_xmlFB(321) % 4
f_xmlFB(035)
};
% Example of a no-loop approach
% ---------------------------
tic
s_exp = #(s, field) [s.(field)];
s_exp_C = #(s, field) {s.(field)};
one = s_exp_C(s_exp( [xmllink{:}], 'Attributes'), 'Name');
two = s_exp_C(s_exp( [xmlFB{:}], 'Attributes'), 'Name');
[i,j] = find(strcmp(repmat(one,numel(two),1), repmat(two,numel(one),1).'));
s_exp_C(s_exp([xmlFB{i}], 'Attributes'), 'Typ')
toc
% Example of a loop approach
% ---------------------------
tic
for ii = 1:numel(xmllink)
S = [xmlFB{:}];
S = [S.Attributes];
S = {S.Name};
ind = strmatch(xmllink{ii}.Attributes.Name, S);
if ~isempty(ind)
xmlFB{ind}.Attributes.Typ
end
end
toc
Output:
% no-loop
ans =
'331' '321' % correct findings
Elapsed time is 0.001103 seconds.
% loop
ans =
331 % correct findings
ans =
321
Elapsed time is 0.000666 seconds. % FASTER!
Granted, it's not a fair test to compare the performance, but I think everyone will agree that the looped version will at the very least not be slower than the non-loop version.
More importantly, speed isn't everything -- how long did it take you to understand the no-loop solution? Chances are you understood the loop solution in one read, whereas the no-loop solution is a lot more complicated and will have to be thoroughly documented and tested etc. Also, changes to the no-loop solution will be harder to implement than changes in the loop solution.
That advice to not use loops in Matlab is completely outdated; please ignore it :)