Use text strings in a cell array in a 'for loop' and also use that text string to name the output
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
I have a list of 9 site names in a column array "sitearray". Those same 9 names appear in a data structure with subfolders, e.g. 9 matrices indexed by 'Data."sitename".matrix'. I would like to perform the same operation on each of the 9 matrices in a for loop e.g. extract the first value of the matrix, and save the output retaining each sitename. I cannot figure out how to link the text of the sitename to the counter variable in the code.
%(Below doesn't work)
for i=1:length(sitearray)
Output_sitearray(i) = Data.sitename(i).matrix(:,[1]);
end
3 Comments
You might be able to use structfun()
Structfun might help but I can't figure out how to use this on all matrixes that are the 3rd level deep in the struct variable. If the data is organized as "Data.sitename.matrix" with 9 sitenames, what Structfun syntax would I use to get an output with the operation done on the "matrix" under each of the 9 sitenames?
S.hello.matrix = [1,2,3];
S.world.matrix = [4,5,6];
F = @(s)s.matrix(1);
V = structfun(F,S)
V = 2×1
1
4
Accepted Answer
Keshav
on 30 Jun 2022
you can use the below code.
for i=1:length(sitearray)
Output_sitearray(i) = Data.(sitename(i)).matrix(:,[1]);
end
13 Comments
Thanks for taking the time to look at this. Now getting an error:
"Argument to dynamic structure reference must evaluate to a valid field name."
Maybe this has something to do with the left hand side? Does not matter if I replace "Output_" with "Output." or remove the "Output_" prefix altogether, or add extra parentheses around "sitearray(i)". Also please consider sitename(i) as equivalent to sitearrary(i), my mistake.
you want to take only first element of matrix or the whole first column?
if you want to take only the first element of matrix, you can use below code.
for i=1:length(sitearray)
Output_sitearray(i) = Data.(sitearray(i)).matrix(1,1);
end
if you want to take whole first column of the matrix, you can use below code. it will basically store the data of ith sitearray in ith column.
for i=1:length(sitearray)
Output_sitearray(:,i) = Data.(sitearray(i)).matrix(:,1);
end
or are you want to do something else?
I believe the error message has something to do with the left hand side "Output_sitearray(i)", the error message is:
"Argument to dynamic structure reference must evaluate to a valid field name."
What I want "Output_sitearray(i)" to be is an output matrix that changes its name with every input site from sitearray, so that I have 9 output matrices at the end of the loop.
When I run your first code it does run but it only gives me one output matrix named "i". I am trying to get 9 output matrices.
Is sitearray a cell array of character vectors, or is it a string array? If it is a cell array of character vectors then the places that @Keshav used sitearray(i) you should use sitearray{i} . Using the (i) form is good if you are using a string array however.
Thanks for the continued advice, I have not succeeded yet. Here is some code to give example matrices. I am not getting the output matrices I want regardless of (i) or {i}. The error code on this now is :
"Reference to non-existent field 's'."
Data.site_a.matrix = [1 2 3];
Data.site_b.matrix = [3 4 5];
Data.site_c.matrix = [6 7 8];
sitearray = ['site_a'; 'site_b'; 'site_c'];
for i=1:length(sitearray)
Output_sitearray(i) = Data.(sitearray(i)).matrix(1,1);
end
change ' to "
Data.site_a.matrix = [1 2 3];
Data.site_b.matrix = [3 4 5];
Data.site_c.matrix = [6 7 8];
sitearray = ["site_a"; "site_b"; "site_c"];
for i=1:length(sitearray)
Output_sitearray(i) = Data.(sitearray(i)).matrix(1,1);
end
Output_sitearray
Thanks for helping me through this! Much appreciated.
What I am looking for at the end of the day are three separate output matrixes, named "Output_site_a" containing a "1", "Output_site_b" containing a "3", "Output_site_c" containing a "6". If that is possible.
you can get a struct with 3 field using the below code
Data.site_a.matrix = [1 2 3];
Data.site_b.matrix = [3 4 5];
Data.site_c.matrix = [6 7 8];
sitearray = ["site_a"; "site_b"; "site_c"];
for i=1:length(sitearray)
Output.(sitearray(i)) = Data.(sitearray(i)).matrix(1,1);
end
Output
but if you want specific different name for every iteration Output_site_a,Output_site_b then i don't think so it is possible. take a look at this question you are also trying to do the same thing.
"What I am looking for at the end of the day are three separate output matrixes, named "Output_site_a" containing a "1", "Output_site_b" containing a "3", "Output_site_c" containing a "6". If that is possible. "
It is certainly possible, if you want to force yourself into writing slow, complex, ineffcient, obfuscated, insecure, buggy code that is hard to debug:
The cause is because you are trying to mix (meta-)data with code, which is best avoided. Accessing your data will be much easier and more efficient if you do not force (meta-)data into variable names.
I appreciate the feedback. I am certainly not trying to force myself into doing something, besides getting the matrices I am looking for. Would you consider writing some code that demonstrates an efficient way to get three separate output matrices? Or if this isn't possible without manually retyping each site name into a matrix in a separate line of code, that would be good to know. To me manually retyping each site name seems potentially buggy. Thanks in advance.
"Would you consider writing some code that demonstrates an efficient way to get three separate output matrices?"
M_hello = ..
M_world = ..
M_other = ..
"Or if this isn't possible without manually retyping each site name into a matrix in a separate line of code..."
I already wrote that it is certainly possible if you want to force yourself into writing slow, complex, inefficient, obfuscated, insecure, buggy code that is difficult to debug.
"To me manually retyping each site name seems potentially buggy."
Yes, probably best avoided.
Best solution: store (meta-)data as data (i.e. in a variable, not in its name). Much simpler to work with.
Question: what are you going to do with your data? How do you wish to process it?
I will try that. Thanks. Keshav, thanks for taking the time to write code specific to the example that stores in a struct, that might work for me.
More Answers (0)
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Tags
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)