Is there an alternative to eval in a struct?

17 vues (au cours des 30 derniers jours)
Yasir Çatal
Yasir Çatal le 21 Oct 2021
Hi,
I know that eval is evil, but in this particular case, I couldn't find any other way to do it, so I wanted to ask you if anyone comes up with a more efficient way.
The problem is, I need to define a struct, and structs inside that struct, and more structs inside that struct. I think it would be better to describe it (simplified) this way:
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
subjects = struct();
% The dirty way, assume that other structs defined previously:
for i = 1:length(subject)
for p = 1:length(runs)
for x = 1:length(roigroups)
for y = 1:eval(strcat('length(',roigroups{x},')'))
subjects.(subject{i}).(runs{p}).(roigroups{x}).(eval(strcat(eval('roigroups{x}'),'{y}'))) = struct();
end
end
end
end
Unrecognized function or variable 'tasks'.
It works really well, manually checked, but it's a pain to write and read. Is there a workaround for this type of task?
  4 commentaires
Akira Agata
Akira Agata le 22 Oct 2021
Still not working.
As shown below, error occurs in the line "subjects.(subjects{i})~" .
subjects = {'subj_1','subj_2','subj_3'};
tasks = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
% The dirty way, assume that other structs defined previously:
for i = 1:length(subjects)
for p = 1:length(tasks)
for x = 1:length(roigroups)
for y = 1:eval(strcat('length(',roigroups{x},')'))
subjects.(subjects{i}).(tasks{p}).(roigroups{x}).(eval(strcat(eval('roigroups{x}'),'{y}'))) = struct();
end
end
end
end
Unable to perform assignment because dot indexing is not supported for variables of this type.
Yasir Çatal
Yasir Çatal le 22 Oct 2021
Sorry, I edited now so that it works. Should've checked before, sorry about that.

Connectez-vous pour commenter.

Réponse acceptée

Matt J
Matt J le 22 Oct 2021
Modifié(e) : Matt J le 22 Oct 2021
Your data organization seems like it should be reconsidered. In a struct, it doesn't make sense if different fields have essentially the same kind of contents. What I think you really want is a 2D or 3D struct array, something like
subject = {'subj_1','subj_2','subj_3'};
tasks = {'rest','task1','task2','task3'};
M=numel(subject);
N=numel(tasks);
a = struct('dlpfc',[],'amyg',[]);
b = struct('insula',[],'postcg',[]);
c = struct('thalamus',[],'nucl_ruber',[]);
[Subjects(1:M,1:N).a]=deal(a);
[Subjects(1:M,1:N).b]=deal(b);
[Subjects(1:M,1:N).c]=deal(c)
Subjects = 3×4 struct array with fields:
a b c
  5 commentaires
Matt J
Matt J le 22 Oct 2021
Modifié(e) : Matt J le 22 Oct 2021
Okay, but is there an intuitive way to see which task/roi etc. belong to which subject?
In your post, all subjects share the same tasks and roigroups. That's why I think an array makes more sense.
for example, I need to exclude some subjects, and when I do that, I don't want every subsequent subject to go up one row and mess everything.
You would have to show an example of "mess everything". Why couldn't you extract a subset of Subjects using integer indices? e.g.,
subset=Subjects([1,5,7],:)
Yasir Çatal
Yasir Çatal le 22 Oct 2021
Thanks to everyone that involved, I guess I should go with subsets.

Connectez-vous pour commenter.

Plus de réponses (2)

Akira Agata
Akira Agata le 22 Oct 2021
I believe it's better to arrange the data as a table rather than the deeply nested structure. How about the following?
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
[p,q,r] = ndgrid(subject, runs, [a,b,c]);
T = table(p(:),q(:),r(:),'VariableNames',{'subject','runs','roi'});
T.roigroups = repelem(roigroups',24,1);
T = movevars(T,'roigroups','Before','roi');
disp(T)
subject runs roigroups roi __________ _________ _________ ______________ {'subj_1'} {'rest' } {'a'} {'dlpfc' } {'subj_2'} {'rest' } {'a'} {'dlpfc' } {'subj_3'} {'rest' } {'a'} {'dlpfc' } {'subj_1'} {'task1'} {'a'} {'dlpfc' } {'subj_2'} {'task1'} {'a'} {'dlpfc' } {'subj_3'} {'task1'} {'a'} {'dlpfc' } {'subj_1'} {'task2'} {'a'} {'dlpfc' } {'subj_2'} {'task2'} {'a'} {'dlpfc' } {'subj_3'} {'task2'} {'a'} {'dlpfc' } {'subj_1'} {'task3'} {'a'} {'dlpfc' } {'subj_2'} {'task3'} {'a'} {'dlpfc' } {'subj_3'} {'task3'} {'a'} {'dlpfc' } {'subj_1'} {'rest' } {'a'} {'amyg' } {'subj_2'} {'rest' } {'a'} {'amyg' } {'subj_3'} {'rest' } {'a'} {'amyg' } {'subj_1'} {'task1'} {'a'} {'amyg' } {'subj_2'} {'task1'} {'a'} {'amyg' } {'subj_3'} {'task1'} {'a'} {'amyg' } {'subj_1'} {'task2'} {'a'} {'amyg' } {'subj_2'} {'task2'} {'a'} {'amyg' } {'subj_3'} {'task2'} {'a'} {'amyg' } {'subj_1'} {'task3'} {'a'} {'amyg' } {'subj_2'} {'task3'} {'a'} {'amyg' } {'subj_3'} {'task3'} {'a'} {'amyg' } {'subj_1'} {'rest' } {'b'} {'insula' } {'subj_2'} {'rest' } {'b'} {'insula' } {'subj_3'} {'rest' } {'b'} {'insula' } {'subj_1'} {'task1'} {'b'} {'insula' } {'subj_2'} {'task1'} {'b'} {'insula' } {'subj_3'} {'task1'} {'b'} {'insula' } {'subj_1'} {'task2'} {'b'} {'insula' } {'subj_2'} {'task2'} {'b'} {'insula' } {'subj_3'} {'task2'} {'b'} {'insula' } {'subj_1'} {'task3'} {'b'} {'insula' } {'subj_2'} {'task3'} {'b'} {'insula' } {'subj_3'} {'task3'} {'b'} {'insula' } {'subj_1'} {'rest' } {'b'} {'postcg' } {'subj_2'} {'rest' } {'b'} {'postcg' } {'subj_3'} {'rest' } {'b'} {'postcg' } {'subj_1'} {'task1'} {'b'} {'postcg' } {'subj_2'} {'task1'} {'b'} {'postcg' } {'subj_3'} {'task1'} {'b'} {'postcg' } {'subj_1'} {'task2'} {'b'} {'postcg' } {'subj_2'} {'task2'} {'b'} {'postcg' } {'subj_3'} {'task2'} {'b'} {'postcg' } {'subj_1'} {'task3'} {'b'} {'postcg' } {'subj_2'} {'task3'} {'b'} {'postcg' } {'subj_3'} {'task3'} {'b'} {'postcg' } {'subj_1'} {'rest' } {'c'} {'thalamus' } {'subj_2'} {'rest' } {'c'} {'thalamus' } {'subj_3'} {'rest' } {'c'} {'thalamus' } {'subj_1'} {'task1'} {'c'} {'thalamus' } {'subj_2'} {'task1'} {'c'} {'thalamus' } {'subj_3'} {'task1'} {'c'} {'thalamus' } {'subj_1'} {'task2'} {'c'} {'thalamus' } {'subj_2'} {'task2'} {'c'} {'thalamus' } {'subj_3'} {'task2'} {'c'} {'thalamus' } {'subj_1'} {'task3'} {'c'} {'thalamus' } {'subj_2'} {'task3'} {'c'} {'thalamus' } {'subj_3'} {'task3'} {'c'} {'thalamus' } {'subj_1'} {'rest' } {'c'} {'nucl_ruber'} {'subj_2'} {'rest' } {'c'} {'nucl_ruber'} {'subj_3'} {'rest' } {'c'} {'nucl_ruber'} {'subj_1'} {'task1'} {'c'} {'nucl_ruber'} {'subj_2'} {'task1'} {'c'} {'nucl_ruber'} {'subj_3'} {'task1'} {'c'} {'nucl_ruber'} {'subj_1'} {'task2'} {'c'} {'nucl_ruber'} {'subj_2'} {'task2'} {'c'} {'nucl_ruber'} {'subj_3'} {'task2'} {'c'} {'nucl_ruber'} {'subj_1'} {'task3'} {'c'} {'nucl_ruber'} {'subj_2'} {'task3'} {'c'} {'nucl_ruber'} {'subj_3'} {'task3'} {'c'} {'nucl_ruber'}

Steven Lord
Steven Lord le 22 Oct 2021
For most of what you're trying to do you could use setfield.
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
subjects = struct();
subjects = setfield(subjects, subject{1}, runs{2}, roigroups{3}, c{1})
subjects = struct with fields:
subj_1: [1×1 struct]
% Checking
subjects.subj_1
ans = struct with fields:
task1: [1×1 struct]
subjects.subj_1.task1
ans = struct with fields:
c: 'thalamus'
For that last input probably I'd make a cell array of cell arrays out of a, b, and c.
D = {a, b, c};
subjects = setfield(subjects, subject{2}, runs{1}, roigroups{2}, D{2}{2})
subjects = struct with fields:
subj_1: [1×1 struct] subj_2: [1×1 struct]
subjects.subj_2.rest.b
ans = 'postcg'

Catégories

En savoir plus sur Structures dans Help Center et File Exchange

Produits

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by