Date: Sun, 1 Oct 2006 17:46:42 -0400
Reply-To: Joe Whitehurst <joewhitehurst@GMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Joe Whitehurst <joewhitehurst@GMAIL.COM>
Subject: Re: Help on Macro for Reading Data
In-Reply-To: <100120061758.9568.452001B900075ED600002560220075074405029A06CE9907@comcast.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Ian,
Since you are going to be in my back yard for a few days, I'll buy you
a few drinks at one of Atlanta's finest outdoor patios and explain
what SCL buys you in the particular example if you will promise not to
invite any mules You rarely mention debugging or performance
monitoring in your sales speeches about the macro facility because, I
suppose, the Macro Facility has only primitive debugging capabilities
and no specific performance monitoring beyond what Base SAS offers.
In contrast, SCL offers a modern debugger and a performance monitoing
tool that monitors performance at the level of individual statements
and functions.
Joe
On 10/1/06, Ian Whitlock <iw1junk@comcast.net> wrote:
> Summary: Macro design with a loop
> #iw-value=3
>
> Sumanta,
>
> You have a helpful answer from Richard, but I will give you more
> to look at and change the emphasis to macro design issues.
> The basic problem with your code is that %DO code must be used
> inside a macro because it must be compiled by the macro facility.
> The RUN statement after "%MEND;" is not needed, since the macro
> compilation ends with the %MEND statement. It is a good idea to
> repeat the name of the macro on the %MEND statement.
>
> The semicolon on the macro invocation is wrong. Macros are
> invoked with the closing parenthesis. Your semicolon is a null
> statement. In this case it doesn't hurt, but if you are in the
> habit of sprinkling null statements in your programs then sooner
> or later you will have a problem and the inability to find it.
>
> To do the processing in one macro, P and Q are the wrong
> parameters. Let's assume the P and Q always have the same range.
> Then consider
>
> %macro myfunc(start=0,stop=3);
> %local p q root ;
> %let root =
> C:\Documents and Settings\happy\Desktop\OIFORECAST ;
> %do p=&start %to &stop ; /* not %-sign on TO */
> %do q=&start %to &stop ;
> PROC IMPORT
> OUT=DATA&p&q
> DATAFILE="&root\try&p&q..csv"
> dbms=csv replace
> ;
> getnames=yes;
> run; /* this RUN is very good and necessary */
> %end ;
> %end ;
> %mend myfunc ;
> /* no RUN */
> %myfunc(start=0,stop=3) /* no semicolon */
> /* run */
>
> Now let's try a design that emphasizes the list involved and
> leads to a more flexible design. At this point it is worth
> giving the macro a more meaningful name.
>
> %macro import(root=,pref=try,list=01 10 20);
> %local i suff ;
> /* init loop */
> %let i = 1 ;
> %let suff = %scan(&list,&i,%str( )) ;
> %do %while ( %length(&suff) > 0 ) ;
> PROC IMPORT
> OUT=DATA&suff
> DATAFILE="&root\&pref&suff..csv"
> dbms=csv replace
> ;
> getnames=yes;
> run;
> /* prepare for next iteration */
> %let i = %eval( &i + 1 ) ;
> %let suff = %scan(&list,&I,%str( )) ;
> %end ;
> %mend import ;
> %import
> ( root = C:\Documents and Settings\happy\Desktop\OIFORECAST
> , pref = try
> , list = 01 10 20 ab )
>
> This code is more flexible because no list with a special
> structure is required. However, it is more burdensome on the
> user because he/she is now responsible for writing the list. To
> remove the burden we can concentrate on the list, since %IMPORT
> already does the job.
>
> %macro mklist ( start = 0 , stop = 3 ) ;
> %local i j list ;
> %do i = &start %to &stop ;
> %do j = &start %to &stop ;
> %let list = &list &i&j ;
> %end ;
> %end ;
> &list /* !!!important NO semicolon */
> %mend mklist ;
>
> Now the macro call will be
>
> %import
> ( root = C:\Documents and Settings\happy\Desktop\OIFORECAST
> , pref = try
> , list = %mklist(start=0, stop=3) )
>
> All of the above work has been tested to see that the expected
> SAS code is generated, i.e. the macro algorithms work. I have
> not tested that the SAS code also works, but I do not see
> anything wrong with the generated code.
>
> Richard used two macros, one to generate a single PROC IMPORT,
> and one to loop through calls to that macro. Now it would be a
> good idea to combine both of our approaches. As an exercise,
> redesign my IMPORT to function as Richard has suggested, but
> still keeping the LIST parameter. For example, say the two
> macros as IMPORTONE and IMPORTALL. Where the invocation of
> IMPORTALL would be
>
> %importall
> ( root = C:\Documents and Settings\happy\Desktop\OIFORECAST
> , pref = try
> , list = %mklist(start=0, stop=3) )
>
> and IMPORTALL would invoke IMPORTONE to generate the SAS code for
> one import.
>
> Now if someone, in particular Richard or Randy, is interested in
> teaching me SCL, would he/she expand Richard's example to have
> the flexibility demonstrated above without the use of macro
> variables. (Please note that the parameters ROOT and PREF could
> be empty. In this case, %IMPORT could import an arbitrary list
> of CSV files spread across several directories as long as no
> spaces are used in the names of the paths. %IMPORT could import
> an arbitrary list.) I am particularly interested in preserving
> the simplicity of Richard's call
>
> proc display cat=sasuser.import.many.scl ...
>
> while emphasizing the parameters of the problem.
>
> Finally, Richard's SCL could be directly translated into a DATA
> step.
>
> data _null_
> do p = 0 to 3;
> do q = 0 to 3;
> call execute
> ( catt('PROC IMPORT
> OUT=DATA',p,q,
> DATAFILE=
> '"C:\Documents and Settings\happy\Desktop\OIFORECAST\try'
> ,p,q,'..csv" dbms=csv
> replace;
> getnames=yes;
> run;')
> end;
> end;
> run;
>
> So what is the advantage of using SCL for this problem? The
> disadvantages are that you must have SAS/AF; you must compile
> code; and then manage the code. What do I gain for the extra
> effort required by SCL in this sort of problem?
>
> Ian Whitlock
> ===============
> Date: Sun, 1 Oct 2006 00:22:29 -0700
> Reply-To: SUM <sumanta24@GMAIL.COM>
> Sender: "SAS(r) Discussion"
> From: SUM <sumanta24@GMAIL.COM>
> Organization: http://groups.google.com
> Subject: Help on Macro for Reading Data
> Comments: To: sas-l
> Content-Type: text/plain; charset="iso-8859-1"
> Hi All,
> I have several datafiles called try01, try10, try20,........ in
> csv
> format. I want to read all these files using the following macro
> but
> it's giving some error. Can anyone help me?
> %macro myfunc(p=,q=);
> PROC IMPORT OUT=DATA&p&q
> DATAFILE="C:\Documents and Settings\happy\Desktop\OI
> FORECAST\try&p&q..csv"
> dbms=csv replace;
> getnames=yes;
> run;
> %mend;
> run;
> %do p=0 to 3;
> %do q=0 to 3;
> %myfunc(p,q);
> %end;
> %end;
> run;
>
> Regards,
> Sumanta.
>
--
To paraphrase G. Santayana, the SAS Macro Facility used by common SAS
programmers is an old mate that gives no pleasure and many headaches,
yet she/he cannot live without it, and resents any aspersions that
strangers may cast on its character
|