Is there an alternative to eval in a struct?

16 Ansichten (letzte 30 Tage)
Yasir Çatal
Yasir Çatal am 21 Okt. 2021
Beantwortet: Steven Lord am 22 Okt. 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 Kommentare
Akira Agata
Akira Agata am 22 Okt. 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 am 22 Okt. 2021
Sorry, I edited now so that it works. Should've checked before, sorry about that.

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Matt J
Matt J am 22 Okt. 2021
Bearbeitet: Matt J am 22 Okt. 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 Kommentare
Matt J
Matt J am 22 Okt. 2021
Bearbeitet: Matt J am 22 Okt. 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 am 22 Okt. 2021
Thanks to everyone that involved, I guess I should go with subsets.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Akira Agata
Akira Agata am 22 Okt. 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 am 22 Okt. 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'

Kategorien

Mehr zu Structures finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by