Automatically create a several layer structure from a cell array

조회 수: 19 (최근 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 CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품


릴리스

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by