TITLE: How to dynamically determine the name of the variable to be called in the function

2 views (last 30 days)
clear
clc
'TITLE: How to dynamically determine the name of the variable to be called in the function"
' I am aware that assigning names dynamically is not efficient, however I need exactly this!'
' Below are two versions describing the problem. '
' Keep in mind that in a later stage id will include more identifiers, ie. id = ["ee", "lv", etc], so I will do the loop. This is why the names need to be determined endogenously. The core problem has to be solved first, but solution needs to be general enough so I can use it in a loop later on ;
'Version 1: produces result that I want. However, some bits are hard coded, not dynamically determined within the code'
'I would like to have XX and YY_ee dynamically determined within the code'
id = 'ee';
Y_eur_ee=[1 2 3]';
varName=strcat('YY_',id);
%XX = who('*ee');
%assignin('caller', varName, XX);
assignin('caller', varName, Y_eur_ee); %the point is that I would like to have names like Y_eur_ee (such as XX) generated within the code and that when I call this name I get the variable (vector) which is already saved in the work space
%Y.level.ee=varName;
Y.level.ee=YY_ee; %the point is that I would like to have names like Y_ee generated within the code (such as varName) and that when I call this name I get the variable (vector) which is already saved in the work space
clear Y_* YY* varName id
'print: Y.level.ee'
Y.level.ee
%--------------------------------------------------------------------------
'=========================================================================='
'version in which XX and YY_ee are dynamically determined within the code, but does not produce result that I want'
id = 'ee';
Y_eur_ee=[1 2 3]';
varName=strcat('YY_',id);
XX = who('*ee');
assignin('caller', varName, XX); % XX is considered to be a string but not the name of the vector, i.e. Y_eur_ee=[1 2 3]';
%assignin('caller', varName, Y_eur_ee);
Y.level.ee=varName;
%Y.level.ee=YY_ee; % YY_ee is considered to be a string but not the name of the vector, i.e. Y_eur_ee=[1 2 3]';
clear Y_* YY* varName id XX
'print: Y.level.ee'
Y.level.ee
return
  8 Comments
Jan
Jan on 17 Jul 2019
[MOVED from section for answers - please post comments as comments - Thanks.]
ferjama30 wrote:
Hello everybody,
Thank you for trying to help :-). I just wanted to say that yes, I have seen number of discussions on how inefficient this is etc. I got the point. But I would nevertheles like to go this way.
To Stephen: yes, I can explain what I am trying to do, maybe it will make more sense. And please, keep in mind that I do not need an efficient code.
So, I have a few data-series for a set of countries. The analysis shall be done for the whole sample, for sub-periods and for subsets of countries. So far, my code is general to the extent that whoever wants to use it, the only thing he/she needs to do is to determine:
- excel file with data-series in EXACT order of countries (Y_aa Y_bb, Y_cc., i.e.:
aa bb cc..
1 4 7
2 5 8
3 6 9
- the subperiods: i.e. period1_start=2000, period2_end=2007, period2_start=2010, period2_end=2018,
Press F5 and the whole analysis is done for 1) whole set of countries, i.e. groupA=['aa' 'bb' 'cc' 'dd' 'ee' 'ff' 'gg'], 2) subset of countries, i.e. groupB=['aa' 'bb' 'cc' 'dd'] and 3) another subset of countries, i.e. groupC=['ee' 'ff' 'gg'],
The subsets’ analyses are implemented by hard coding the appropriate matrices for those sets of countries. In fact all the naming is done by hard core coding, ie.:
groupA:
groupA_Y=[Y_aa Y_bb Y_cc Y_dd Y_ee Y_ff Y_gg]
groupA_X=[X_aa X_bb X_cc X_dd X_ee X_ff X_gg]
groupA_Z=Y./X
groupB:
groupB_Y=[Y_aa Y_bb Y_cc Y_dd ]
groupB_X=[X_aa X_bb X_cc X_dd ]
groupB_Z=Y./X
groupC:
groupC_Y=[Y_ee Y_ff Y_gg]
groupC_X=[X_ee X_ff X_gg]
groupC_Z=Y./X
It is unnecessary replicating stuff. I anddition, whoever wants to change the groups, has to manually change all the definitions of the groups in te code...
Now, I want to make this easy for a random person user (who is potentially not a matlab regular user) to be able to:
- construct excel file with RANDOMorder for variables
- the sub-periods part: this is already fine
- define group of countries for which analysis shall be done, i.e. groupR=['cc' 'ee' 'ff' 'gg' 'ii']
- all the rest being automatic.
F5 and the analysis shall be done for groupR by matlab going into the excel file finding exactly the right columns cc ee ff gg ii - independently of where (in which column) they might be and construct the right variable names with associated vectors and matrices for groupR. So, by defining groupR, the code should go and find cc ee ff gg ii attach it to Y_cc Y_ee Y_ff Y_gg Y_ii and appropriate X_* and put them into matrix groupR_Y=[ Y_cc, Y_ee, Y_ff, Y_gg, Y_ii] and appropriate groupR_X. Doing all the rest is already done.
If at any point in time that user wats to print out exactly Y of county cc (Y_cc), he will be able to do so. If he want to access Y of the groupR, he can get group Y of all countries in the group (groupR_Y).
Suppose next year somebody wants to add another county to the analysis, call it 'mu'. The only thing he should do is to attach a vector of data for 'mu' somewhere into the excel file and add 'mu' to the country group identifier groupR=['cc' 'ee' 'ff' 'gg' 'ii' 'mu'].
I agree, a way easier way would be just to index the countries but then one needs to keep the order in mind... I want to do the code for dummies, where knowing how open do_file, enter a few letters within first few lines and press F5 is sufficient. Basically, this would be pretty much equivalent to having interface where one needs to define countries in the analysis and rest is done automatically.
Efficiency of the code is of no importance in this case. The whole procedure does not need cumbersome iterations, it is just automatizing a few simple outputs; being inefficient and needing a minute or two more really doesn't matter.
Alternative solutions are of course welcome, as long as the main goal i.e. construct the do_file for dummies is preserved. :-)
Adam
Adam on 17 Jul 2019
Edited: Adam on 17 Jul 2019
I still don't get how you can't simply replace any of your dynamically named variables with a field on a struct though. Instead of YY_ee etc dynamically named, just
YY.( id )
with
id = 'ee';
as you already have. Then it can still be referred to either directly as
YY.ee
later on, or via a dynamic string again as
YY.( id )
e.g. something like this:
fGetFields = @(s,fieldnames) cellfun( @(field) s.(field), fieldnames );
groupC_fields = {'ee' 'ff' 'gg'};
groupC.Y = fGetFields( YY, groupC_fields );
though there are probably neater ways too.
The very fact you have a quite complex attempt at dynamically naming the variables themselves and need to ask for advice already suggests that it is problematic to do. And once you have named them in the first place, somewhere later down the line you will need to access them again, which requires another complicated bunch of code, as oppose to the simplicity of the dynamic field on a struct.
Obviously there's no problem with asking for help, but since you clearly know a decent amount about Matlab already, getting into a position where you need to ask for help is always a good point to consider if the reason you need help is because what you are doing is just generally a very difficult problem.

Sign in to comment.

Answers (1)

Jan
Jan on 17 Jul 2019
I do not get the point.
"excel file with data-series in EXACT order of countries (Y_aa Y_bb, Y_cc., i.e.:
aa bb cc.."
Where is the need to call this "Y_aa"? If the order is fixed, you can import the data as a matrix and access the columns by standard indexing.
There is no need for numbered variables for the periods also:
"period1_start=2000, period2_end=2007, period2_start=2010, period2_end=2018,"
Why not:
period_Start = [2000, 2010]
period_End = [2007, 2018]
It is not 100% clear, what is meant by an unexplained notation, which is not valid Matlab syntax:
groupA=['aa' 'bb' 'cc' 'dd' 'ee' 'ff' 'gg']
In Matlab this means:
groupA='aabbccddeeffgg'
Of course, I can try to guess, what you mean. But guessing is the main cause of missunderstandings.
"groupA_Y=[Y_aa Y_bb Y_cc Y_dd Y_ee Y_ff Y_gg]"
If this is hard coded and teh order of columns is fixed only, this would be much easier:
groupA_ind = [1, 2, 3, 4, 5, 6, 7];
groupA = Data(:, groupA_ind)
To increase the level of clarity, you can use a table object also and apply the headers of the columns as names. Structs are fine also:
Countries = {'aa', 'bb', 'cc', 'dd'}
% Assuming that Data was imported as a matrix
DataC = num2cell(Data, 1);
DataS = cell2struct(Countries, DataC, 2);
Then you do not use "Y_cc", but DataS.cc. This is efficient, clean, stable, easy to debug, to maintain and to expand.
If several "groups" are existing, then group(1).cc is fine also. Indirections over hiding indices in the names of variables will increase the complexity of the code without any benefit.
"I want to do the code for dummies"
Then keep it simply stupid instead of a meta-programming, which processes the names of the variables instead of their contents by indexing.
  2 Comments
Guillaume
Guillaume on 18 Jul 2019
I've only skimmed over ferjama30's explanations but it looks to me the whole thing could easily be implemented in terms of tables which would greatly simplify the code and at the same time be a lot easier to use by "dummies".
Grouping data using one or more table variables is trivially done in matlab. It's just one line of code!
Steven Lord
Steven Lord on 18 Jul 2019
I share Guillaume's impression. Read the data from Excel into a table array using readtable. Once your data is in table form you can retrieve rows by number or by row name or variables by number, name, or type. See the Access Data in a Table documentation page for a summary and examples.
Many of the data preprocessing functions (including groupsummary, which is the function I believe Guillaume had in mind) can accept a table.

Sign in to comment.

Categories

Find more on Structures in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!