Automatically create a several layer structure from a cell array

22 views (last 30 days)
Hello,
I have a signal that vary along three parameters a,b and c wich can take several values.
a can take n different values a1,a2...an
b can take m different values b1,b2,...,bm
c can take p different values c1,c2...cp.
So far I have all the variations stocked in a cell array C of size n*m*p such that C(x,y,z) correspond to my signal with parameter ax, by and cz.
This works but is not very easy to use. Let's say I want to get the signal corresponding to certain parameter I first need to go find the indexes of the wanted parameters (because I know the value of a that I want but not the index to wich it correspond).
My idea was to create a structure S such that
S.ax.by.cz=C(x,y,z)
that way I wont need a correpondance table
So far the only way to do it that I found is
for i=1:n
for j=1:m
for k=1:p
S.(a_value(i)).(b_value(j)).(c_value(j))=C(i,j,k)
end
end
end
I was wondering if a nicer/more efficient solution exist?
PS: I can't put the value directly in the structure when I generate it because the generation is inside a parfor loop. If you have a solution to that issue that would also solve my problem
thanks in advance
  7 Comments
Stephen23
Stephen23 on 8 Mar 2023
Aaaah, so you actually have text data.... in which case, a few dynamic fieldnames as you show is probably reasonably efficient. Dynamic fieldnames in some loops is likely the most efficient approach (you could use SETFIELD, but it is slower).
The approach you show is not easily generalizable nor easily expandable.
Voss
Voss on 8 Mar 2023
"forcing meta-data into variable names should be avoided"
Yes, you are right. I was following @Matteo Bonhomme's naming pattern, so that he could easily see how the nested function would work.
"The approach you show is not easily generalizable nor easily expandable."
I disagree.

Sign in to comment.

Answers (1)

Eric Sofen
Eric Sofen on 14 Mar 2023
Another approach is to string this out into a table, converting what were labels along each dimension into grouping variables. Starting with the same salary data example, the trick is to use ndgrid.
salary=arrayfun(@(x) x,randi(100000,[2,2,2]),'UniformOutput',false);
job_array=["doctor","waiter"];
country_array=["USA","France"];
age_array=["less_than_40","more_than_40"];
salary = [salary{:}]'
salary = 8×1
13085 40527 9337 23364 27223 34191 94748 16327
[Job, Country, Age] = ndgrid(job_array,country_array,age_array)
Job = 2×2×2 string array
Job(:,:,1) = "doctor" "doctor" "waiter" "waiter" Job(:,:,2) = "doctor" "doctor" "waiter" "waiter"
Country = 2×2×2 string array
Country(:,:,1) = "USA" "France" "USA" "France" Country(:,:,2) = "USA" "France" "USA" "France"
Age = 2×2×2 string array
Age(:,:,1) = "less_than_40" "less_than_40" "less_than_40" "less_than_40" Age(:,:,2) = "more_than_40" "more_than_40" "more_than_40" "more_than_40"
t = table(Job(:), Country(:), Age(:), salary, VariableNames=["Job", "Country","Age","Salary"])
t = 8×4 table
Job Country Age Salary ________ ________ ______________ ______ "doctor" "USA" "less_than_40" 13085 "waiter" "USA" "less_than_40" 40527 "doctor" "France" "less_than_40" 9337 "waiter" "France" "less_than_40" 23364 "doctor" "USA" "more_than_40" 27223 "waiter" "USA" "more_than_40" 34191 "doctor" "France" "more_than_40" 94748 "waiter" "France" "more_than_40" 16327
% Now you can either use logical indexing to select data or grouping to do
% calculations that would be equivalent to slicing in your original array:
t.Salary(t.Job=="waiter" & t.Country == "France" & t.Age == "less_than_40")
ans = 23364
groupsummary(t,"Country","mean","Salary")
ans = 2×3 table
Country GroupCount mean_Salary ________ __________ ___________ "France" 4 35944 "USA" 4 28756

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!