Desktop productivity for business analysts and programmers

%array and %do_over are not recognized in SAS EG 5.1

Reply
Contributor
Posts: 27

%array and %do_over are not recognized in SAS EG 5.1

Hello I am using the following code:

 

%macro test;

%ARRAY(yrs,VALUES=1983-1986);

%let Temp= %DO_OVER(yrs);

%mend test;

%test;

%put &Temp;

 

Here's my sas log:

 

1 %_eg_hidenotesandsource;

5 %_eg_hidenotesandsource;

22

23 %macro test;

24 %ARRAY(yrs,VALUES=1983-1986);

25 %let Temp= %DO_OVER(yrs);

26 %mend test;

27 %test;

NOTE: Line generated by the invoked macro "TEST".

27 %ARRAY(yrs,VALUES=1983-1986);

_

180

WARNING: Apparent invocation of macro ARRAY not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent invocation of macro DO_OVER not resolved.

WARNING: Apparent invocation of macro DO_OVER not resolved.

28 %put &Temp;

%DO_OVER(yrs)

29

30 %_eg_hidenotesandsource;

42

43

44 %_eg_hidenotesandsource;

47

 

 

My software does not seems te recognized %array and %do_over;

 

First question: Why?

If it is not possible to correct this situation, what can I do to achieve the same task?

 

Regards,

Alain

Super User
Super User
Posts: 7,407

Re: %array and %do_over are not recognized in SAS EG 5.1

[ Edited ]

"Why?" - this is simple, there is no such thing as %array in the SAS language, either in Base SAS or Macro SAS, therefore the operation is invalid.  Nor in fact is there a %do_over function in the SAS language.

 

Question from me, why do data processing in a text generation language in the first place?  Datastep (Base) is the language in which data processing is done, and that has all the constructs such as arrays for such a purpose.  Macro language only creates text, it doesn't do anything itself.  You can use a few constructs in Macro, such as:

%do i=1983 %to 1986;
...
%end;

However these are pretty basic and are only creating text at the end of the day.

Super User
Super User
Posts: 6,502

Re: %array and %do_over are not recognized in SAS EG 5.1

Those are not SAS provided macros. You need to tell SAS how to find the definition of those macros.  Either %INCLUDE the source code or setup SASAUTOS to point to the location where SAS can find the source code.

PROC Star
Posts: 7,363

Re: %array and %do_over are not recognized in SAS EG 5.1

%array and %do_over do not, as far as I know, exist. Let us know what you're trying to accomplish (with example have and want datasteps) and someone will be able to show you how to do it.

 

Art, CEO, AnalystFinder.com

Contributor
Posts: 27

Re: %array and %do_over are not recognized in SAS EG 5.1

What the purpose of the attached pdf document if the macro %do_over and %array do not exist?

 

Anyway...

 

What I would like to do is to make two macro variables which contains a list of values such as:

 

%let list1=15020 54330 54350 55080 65110 68020 80110
%let list2= 54090 54320 55020 80100 80110 80180 80200 90010

 

I would like to put those two macro variables at the begining of the sas program to permits the user to see those code and to change those if necessary.

 

There after, I would like to use those two macro variables in order to reproduce the code below, using a do loop statement.

It is why I have looked at the %array and %do_over, macro function that does not exist.

 

Does anyone could provide me such suggestions?

Regards

Alain

 

 

 

data donneesTrans (drop=totIndUnRisq totVed i);

 length ind15020 ind54330 ind54350 ind55080 ind65110 ind68020 ind80110 
           ved54090 ved54320 ved55020 ved80100 ved80110 ved80180 ved80200 ved90010 4;

 set donneesTrans;
 array unite{*} unite1-unite&DimVect;
 do i=1 to &DimVect;
  if unite(i)=15020 then ind15020=1;
  if unite(i)=54330 then ind54330=1;
  if unite(i)=54350 then ind54350=1;
  if unite(i)=55080 then ind55080=1;
  if unite(i)=65110 then ind65110=1;
  if unite(i)=68020 then ind68020=1;
  if unite(i)=80110 then ind80110=1;

  if unite(i)=54090 then ved54090=1;
  if unite(i)=54320 then ved54320=1;
  if unite(i)=55020 then ved55020=1;
  if unite(i)=80100 then ved80100=1;
  if unite(i)=80110 then ved80110=1;
  if unite(i)=80180 then ved80180=1;
  if unite(i)=80200 then ved80200=1;
  if unite(i)=90010 then ved90010=1;
 end;

 if ind15020=. then ind15020=0; 
 if ind54330=. then ind54330=0;
 if ind54350=. then ind54350=0;
 if ind55080=. then ind55080=0;
 if ind65110=. then ind65110=0; 
 if ind68020=. then ind68020=0;
 if ind80110=. then ind80110=0;

 if ved54090=. then ved54090=0;
 if ved54320=. then ved54320=0;
 if ved55020=. then ved55020=0;
 if ved80100=. then ved80100=0;
 if ved80110=. then ved80110=0;
 if ved80180=. then ved80180=0;
 if ved80200=. then ved80200=0;
 if ved90010=. then ved90010=0;
run;
 

 

 

PROC Star
Posts: 7,363

Re: %array and %do_over are not recognized in SAS EG 5.1

Actually, they both exist but aren't macro functions, per se, but rather macros written by a SAS user. They can be downloaded from:http://www.sascommunity.org/wiki/File:Clay-TightLooping-macros.zip

 

If your not familiar with SAS macros, you have to first download and unzip the file, then run the two (or if you want, all three macros).

 

Then you can use them as described in the paper about them.

 

Art, CEO, AnalystFinder.com

 

Contributor
Posts: 27

Re: %array and %do_over are not recognized in SAS EG 5.1

Thank you for providing me the web site where to download those macro.

Regards,

Alain

Super User
Super User
Posts: 7,407

Re: %array and %do_over are not recognized in SAS EG 5.1

Firstly, you can halve your code straight off by using ifn/ifc functions:

data donneesTrans (drop=totIndUnRisq totVed i);
 length ind15020 ind54330 ind54350 ind55080 ind65110 ind68020 ind80110 
           ved54090 ved54320 ved55020 ved80100 ved80110 ved80180 ved80200 ved90010 4;
 set donneesTrans;
 array unite{*} unite1-unite&DimVect;
 do i=1 to &DimVect;
    ind1520=ifn(unite(i)=15020,1,0);
    ind5430=ifn(unite(i)=54330,1,0);
...
 end;
run;

This way you don't need the second part for setting the zeros.

 

Second point, putting data into macro lists is rarely a good idea, it can both bloat the code you need to do (i.e. all the looping over an such like) and make hard to maintain code.  Put your lists into datasets - datasets are there to hold data.  Then you merge data together and process.  So say I have the lists as:
LIST_NO  LIST1  LIST2 ...

1               15020  54330...

2               54090  54320...

 

It is then a pretty simple task to merge either of those lists onto the data and then code the check as:

data want;
  merge have lists (where=(list_no=1));
  array unite{*} unite:;    /* Note the shorthand use of : to indicate */
  array list{*} list:;              /* all variables starting with the text */
  do i=1 to dim(unite);
    do j=1 to dim(list);
      if unite{i}=list{j} then found_value=list{j};
    end;
  end;
run;

      

This just loops over list and sets foun variable to value if it matches.  Very simple, short logic.

Contributor
Posts: 27

Re: %array and %do_over are not recognized in SAS EG 5.1

Very good comments.  I will take that into consideration for the future.

Regards,
Alain

Super User
Super User
Posts: 6,502

Re: %array and %do_over are not recognized in SAS EG 5.1

[ Edited ]

It is best not to use code generation (macros) to do things that you can do directly with SAS.

In this case it looks like you want to input two lists of code values (IND and VED) and generate series of flag variables to indicate if those codes appear in the set of input variables (UNITE1 ....).

It would probably be better to produce mulitple observations instead of multiple columns with the code value stored in the variable name.  But even with this wide structure you do not need to resort to macro looping. Instead just use macro functions to generate the dynamic variable names.

 

%* Set the code lists ;
%let indlist=15020 54330 54350 55080;
%let vedlist=54090 54320 55020 80100;

%* generate variable names from code lists;
%let indvars=ind%sysfunc(tranwrd(%sysfunc(compbl(&codelist)),%str( ),%str( ind)));
%let vedvars=ved%sysfunc(tranwrd(%sysfunc(compbl(&codelist)),%str( ),%str( ved)));

%* Need count to generate _temporary_ array ;
%let nflags=%sysfunc(countw(&indlist &vedlist));

data want;
  set have;
  array flags 4 &indvars &vedvars;
  array values (&nflags) _temporary_ (&indlist &vedlist);
  do i=1 to dim(flags);
    flags(i) = 0<whichn(values(i),of unite1-unite&DimVect);
  end;
  drop i;
run;

 

 

Contributor
Posts: 27

Re: %array and %do_over are not recognized in SAS EG 5.1

Thanks for the SAS program.

Regards,

Alain

Ask a Question
Discussion stats
  • 10 replies
  • 156 views
  • 0 likes
  • 4 in conversation