Pergunta

I am new to SAS macro writing and I have been struggling with writing a code for the following instance.

I have a list that is a combination of comp_id and date as follows -

DATA compno_date_list; 
  INPUT compno sdate; 
  DATALINES; 
12490 20090120 
87432 20090120
24643 20090120
87432 20090119
12490 20090105
24643 20090105
;

Now, this is a sample list. I need to run a huge macro on this list on a very large dataset. Since doing it for every row i.e. comp_ID - date combination will take a lot of time, I plan to select unique dates and create a macro variable that has all the dates. For each date in this macro variable, I need to create a macro variable that has the list of comp_IDs pertaining to that date. So, I plan to run the following macro that generates 'n' macro variables where 'n' is the total number of dates as follows -

%MACRO GET_MACRO_VARS();
%let j = 1;
%let sdate3 = %scan(&sdate1., &j.);
%do %while(&j.<= &ndate.);

proc sql;
  select distinct compno into : n&j.
  separated by ' '
 from compno_date_list where sdate=&sdate3.;
%let j= &j. + 1;
%let sdate3 = %scan(&sdate1., &j.);
%put &j.; 
%put &sdate3.;
%put &(n&j);

%end;
%mend;

%GET_MACRO_VARS();

Here, sdate1 is the macro variable containing all unique dates and ndate is a macro variable with the count of total unique dates.

But if I run this code, I get the following values in my log file from my last 3 %put statements in the macro above -

1 + 1
20090105
&(n1+ 1)

i.e. j is being treated as character variable(?). WHy is this happening and how do I rectify this? Thanks!

Foi útil?

Solução

SAS recursively resolves everything that starts with a "%" or a "&". For a %let statement it stores everything to the right of the equal sign into the macro variable as a string (macro variables are always strings).

For "%let j= &j. + 1;" it does the following:

  1. Resolve the "&j" so that you're left with "%let j= 1 + 1;";
  2. Since SAS doesn't see anything starting with a % or a & to the right of the equal sign it sets j to "1 + 1".

In order to increment j you need to change the line to "%let j=%eval(&j + 1);". So the steps become the following:

  1. Resolve the innermost "%" or "&" which is "&j", so the line becomes "%let j=%eval(1 + 1);".
  2. Resolve the "%eval(1 + 1)" so the line becomes "%let j=2;".
  3. Set j to "2".

Also the syntax for getting the value of a variable where the name is defined by another variable is &&n&j so &(n&j) wouldn't work.

Having said that, an easier way to do what you're trying to do is the following:

%do j=1 %to %sysfunc(countw(&sdate1));
  proc sql;
    select distinct compno into : n&j separated by ' '
    from compno_date_list where sdate=%scan(&sdate1, &j);
  quit;
  %put &&n&j;
%end;

One thing to note is if you're processing a large dataset you might want to try to avoid going over it for each date by either using multiple output data sets in a data step or using hash objects if possible since this seems like a very time consuming task.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top