Automatically create a several layer structure from a cell array

22 ビュー (過去 30 日間)
Matteo Bonhomme
Matteo Bonhomme 2023 年 3 月 8 日
回答済み: Eric Sofen 2023 年 3 月 14 日
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 件のコメント
Stephen23
Stephen23 2023 年 3 月 8 日
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 2023 年 3 月 8 日
"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.

サインインしてコメントする。

回答 (1 件)

Eric Sofen
Eric Sofen 2023 年 3 月 14 日
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

カテゴリ

Help Center および File ExchangeLogical についてさらに検索

製品


リリース

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by