Learning SAS? Welcome to the exclusive online community for all SAS learners.

Access to generic created macro variables

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 6
Accepted Solution

Access to generic created macro variables

Hi,

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,

Jan

(1)

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, ':'));

i=i+1;

end;

(2)

do while (i=10);

        if age_year = cat('&klassContVal',i) then age_year_class = cat('&klassCont', i);

i=i+1;

end;


Accepted Solutions
Solution
‎12-04-2014 10:51 AM
Super User
Posts: 19,772

Re: Access to generic created macro variables

Posted in reply to jan_metzger

Look at symget function

View solution in original post


All Replies
Super User
Super User
Posts: 7,942

Re: Access to generic created macro variables

Posted in reply to jan_metzger

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.

This:

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.

Occasional Contributor
Posts: 6

Re: Access to generic created macro variables

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.).

 
{1:20,2:40,3:50,4:60,:5,missing:10,}

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 Smiley Wink

best regards,

Jan

Super User
Super User
Posts: 7,942

Re: Access to generic created macro variables

Posted in reply to jan_metzger

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):

CLASS     UPPER_BOUND

1               20

2               40

...

Then later on when you need to use this just do:

data _null_;

     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;');

run;

Super User
Super User
Posts: 7,942

Re: Access to generic created macro variables

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.

Occasional Contributor
Posts: 6

Re: Access to generic created macro variables

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.

sas_config_csv.PNG

Super User
Super User
Posts: 7,942

Re: Access to generic created macro variables

Posted in reply to jan_metzger

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;

        I=1;

        do while (scan(classcount,i,',') ne "");

          current_text=scan(classcount,i,',');

          class=scan(current_text,1,":");

          high_bound=scan(current_text,2,":");

          output;

          I=I+1;

        end;

     end;

...

Then you can use those parameters later on as a dataset without needing to further process them.

Occasional Contributor
Posts: 6

Re: Access to generic created macro variables

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));

i=i+percentileSize;

end;

Thanks in advance,

Jan

Solution
‎12-04-2014 10:51 AM
Super User
Posts: 19,772

Re: Access to generic created macro variables

Posted in reply to jan_metzger

Look at symget function

New Contributor
Posts: 2

Re: Access to generic created macro variables

Posted in reply to jan_metzger

Hi Jan,

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:

data step2;

set in;

%do i = 1 %to 10;

    if age_year = &&ClassContVal&i then age_year_class = &&ClassCont&i ;

%end;

run;

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:

    &&ClassContVal&i

     &ClassContVal1

     bananas

Hope this helps!

Super User
Posts: 19,772

Re: Access to generic created macro variables

Posted in reply to jan_metzger

If you're recoding variables, you're better off using proc format and skipping the macro variables route entirely.

Trusted Advisor
Posts: 3,212

Re: Access to generic created macro variables

Posted in reply to jan_metzger

Is using variable lists in SAS not far more easy?

SAS(R) 9.4 Language Reference: Concepts, Fourth Edition

A lot of other languages do not have that concept. Why building something that is already there?

---->-- ja karman --<-----
Occasional Contributor
Posts: 6

Re: Access to generic created macro variables

: 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?

Trusted Advisor
Posts: 3,212

Re: Access to generic created macro variables

Posted in reply to jan_metzger

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.   

---->-- ja karman --<-----
🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 13 replies
  • 908 views
  • 0 likes
  • 5 in conversation