12-04-2014 08:07 AM
we are currently doing some work with sas studio. Is it somehow possible to access the the value of the created macro variable classCont1 with the help of the concatenated string classCont1 ( cat('classCont' , 1)).
If you want to take a look at the code, please look at (1) and (2) at the bottom.
In our program we are creating macro variables within a do while loop, for example we have created the classCont1 - classCont10 macro variables per call symput statement within a do while loop with the help of the cat() function and the variable i. (1)
So basically what we want to do in the next step is to go from classCont1-classCont10 and to execute code based on the condition if a if statement is true.
The Problem here is that we somehow need to go through the different classCont variables but we dont know how.
We tried to do it with a do while loop, but we can only build a string, not access the value of the macro variable with the same name. (2)
so how is it possible to access value klassCont1 with the help of a concatenated statement that builds the string klassCont1?
we would really appreciate your help since the hole program depends on the ability to do that.Thanks in advance,
do while (i=<j);
call symput ((cat('m_classCont', i)),
scan(scan(klassCont, i , ','), 1, ':'));
call symput ((cat('m_classContVal', i)),
scan(scan(klassCont, i , ','), 2, ':'));
do while (i=10);
if age_year = cat('&klassContVal',i) then age_year_class = cat('&klassCont', i);
12-04-2014 08:40 AM
Sorry, you don't state why you need to use so many macro variables in the first place. There's almost never a need to do things that way.
Personally I don't know SAS Analytics, so can't be specific on that, but in SAS there is a table called SASHELP.VMACRO which holds the macro results. You could use that. I am also not sure about your use of the functions.
call symput ((cat('m_classCont', i)),
Doesn't do anything. symput requires a name for the macro variable, and some data that it would represent:
symput(<name of macro variable>,<data it is to represent>)
Not sure what you are trying to achieve with this code:
scan(scan(klassCont, i , ','), 1, ':'));
Why do you have klassCont and classCont, are they the same??
Maybe start by clearly defining what you have and what you want to achieve.
12-04-2014 10:48 AM
Hi, thanks for answering.
We have an external csv that we want to use to configure a Project. The Goal is to only make changes in the config.csv to customize the whole project (columns, filepath, delimiter, classification (continuous, percentiles etc.) etc.).
this is a input example for the continuous classification with different classes for our classification (below 20 is class 1, below 40 class 2. etc.)
The amount of classes can vary from project to project.
The scan part is the 2nd parameter of the symput statement and creates a string. (scan the string for the delimiter and then take the x word) The following statement creates classCont1 (classification continuous) with 1 and the classContValue 20. We put that into a do while loop so the whole string is parsed I posted above is parsed into the classes and the value macro variables.
call symput ((cat('m_classCont', i)), scan(scan(classCont, i , ','), 1, ':'));
call symput ((cat('m_classContVal', i)), scan(scan(classCont, i , ','), 2, ':'));
sorry 4 the klass\class mistake, we have started to code in german and then changed the name from klass (klassifikation) to class (classification but it seems i have forgot that part
12-04-2014 12:04 PM
So you read in from CSV, and get a dataset something like (and this is probably key, get your data into a usable format - x:y doesn't seem to be the best way):
Then later on when you need to use this just do:
set csv_data end=last;
if _n_=1 then call execute('data want_with_assign; set data_i_have;');
call execute(' if value < '||strip(put(upper_bound,best.))||' then class='||strip(put(class,best.))||';');
if last then call execute('run;');
12-04-2014 01:43 PM
I was thinking after sending that code that I could have simplified it. In you input dataset from the CSV, just have a Lower bound also (lower_bound=lag(upper_bound)). Then you could simply merge the class onto your data where value between lower and upper bounds. You could also use formats as Reeza has mentioned.
Anyways, the point is, get your information from the CSV and organise it into a dataset you can use. That way you can use basic SAS steps to do almost anything.
12-04-2014 02:25 PM
Wow, you´re really great, so many answers that quick!
what i tried so far is to use symget to Access the macro variable through a concatenated string. That worked well so far.
Our first Idea was to do it with a Array, but the difficulty was to create a Array with the right size and names. One Problem is there is the varying amount of classes, the lack of knowledge if it is possible to append something to the Array and to guarantee Access from .another data step.
I´ve attached a Picture how the config.csv Looks like. The reason we used the x:y Notation is to make the configuration as comfortable as possible.
@ehehedhd : the part (2) is within another data step, i just inserted only a part of the code in here.
12-05-2014 04:37 AM
Yes, not so worried about how the input Excel file looks. Its more to do with how you process that after import. So read in the text then have a datastep to arrange the input into a useable format. For instance:
data other_data class_parameters;
if type="classification" then do;
do while (scan(classcount,i,',') ne "");
Then you can use those parameters later on as a dataset without needing to further process them.
12-11-2014 04:48 AM
The part with the continuous classification is done. Using the symget statement was the key.
Now we are doing the classification with percentiles. We´ve used proc univariate to calculate the boundaries for our classes with the help of our class size (percentile size) in our config.csv. These boundaries are now stored in a sas dataset.
What we now have to do is to store these values within variables, macro variables or access the dataset directly.
The problem is that there can be p20-p80 percentiles or p10-p90 or something else, so how can i access these generic values?
We tried to do it with a call symput statement, but the 2nd value of the call symput statement only inserts a string into our macro variable. (See code below)
do while (i<=100);
call symput(cat('p',i), cat('p',i));
Thanks in advance,
12-04-2014 11:41 AM
If I'm understanding correctly, it looks like you want your line near the bottom to resolve as follows:
"If age_year is equal to <the value stored in ClassContVal1> then..." when i = 1, <the value stored in ClassContVal2> when i = 2, etc.
If so, more ampersands is probably what you need.
First off, I think your part (1) and part (2) need to be done in separate data steps - the macro variables' values are normally read at compilation, so they won't have been set yet in (2) if there isn't a run; after (1).
Secondly, I presume (1) sets them up for all rows read in (2)? I.e. each record in the dataset doesn't set up its own values? If it did, you want arrays rather than macro variables I'd say.
Once you've got that though, I think your (2) ends up looking like:
%do i = 1 %to 10;
if age_year = &&ClassContVal&i then age_year_class = &&ClassCont&i ;
When SAS is compiling macro language, it does multiple passes through if it encounters multiple ampersands, turning two into one on the first pass then going again. In this case, if the value stored in ClassContVal1 is bananas, the compilation would go:
Hope this helps!
12-04-2014 02:24 PM
Is using variable lists in SAS not far more easy?
A lot of other languages do not have that concept. Why building something that is already there?
12-04-2014 02:33 PM
: we tried to do it with the variable list, the Problem was just that we don't exactly know how many variables we Need. so the declaration of the variable list was difficult. We didnt find a way to use a numeric variable with the exact amount within the variable list creation to create a variable list that is large enough but not to large.
Is it possible to Access the variable list from within another data step?
12-04-2014 03:26 PM
Let me think, you are trying to build some code generator that will read that excel and than do some predefined tasks with that.
The issue is you have something to klassFree en klassCont that is build with a lot of variation.
Procedures and SAS datasteps work an dataset variables, the question is what variation in that is needed.
The SAS macro language can be used to manipulate that code. Do you have already a structure and some logic of those. See SAS macro language only as manipulating that as text. Macro-variables are on text- strings.
By that you can propagate all kind of definitions from one sas-datastep to another (arrays and variable lists definitions)
The SAS datasteps and procs will get those defined lists and can be defined generic retrieving those dimensions.
Setting conditions stored in macro-vars parts of the text/code what you are generating can be tailored in almost any way .
Anyway what do you have as datastep/procs s process to start with as a simple start?
Than working back and more impovements/addons.
Need further help from the community? Please ask a new question.