Desktop productivity for business analysts and programmers

IF then DO to select your data sets

Reply
N/A
Posts: 0

IF then DO to select your data sets

I am trying the run the piece of code below. I have a variable above this code that defines cScenario as "PortfolioDaily" or "PortfolioMonthEnd". For this discussion, cScenario does equal "PortfolioDaily". Is it possible to use a DO statement when selecting my data sets? It doesnt appear to be working when I run my code.


DATA test;

If "&cScenario"="PortfolioDaily" then do;

SET port.dlscad (KEEP= &keeplist5)
port.secdcad (KEEP= &keeplist3)
port.dlscbna (KEEP= &keeplist5)
port.secdcbna (KEEP= &keeplist3);
end;
else do;
SET pmport.dlscad1 (KEEP= &keeplist5)
pmport.secdcad1 (KEEP= &keeplist3)
pmport.dlscbna1 (KEEP= &keeplist5)
pmport.secdcbna1 (KEEP= &keeplist3);
end;

run;

Message was edited by: VtNick Message was edited by: VtNick
SAS Super FREQ
Posts: 8,819

Re: IF then DO to select your data sets

Hi:
What you describe is fairly standard macro conditional logic. There is a difference between data step logic and macro conditional logic, in both syntax and "timing".

Since SAS looks at the SET/KEEP statement in order to build the program data vector for your program (and be sure it has the right variable names) -- even though you have your set statement inside data step conditional logic, SAS still sees both of your SET/KEEP statements at compile time. So the fact that you're getting an error and incorrect or no output means that you have to build your set statements conditionally -- and this points to using SAS Macro conditional logic, not data step logic. If you remove the KEEP= option from your code, you may avoid getting error messages, and you may in fact get output, but it's really better in this instance to move to the use of macro logic instead of data step logic.

In order to turn this into a correct macro program that uses conditional logic you generally should follow these steps:
1) have a working SAS program (or in your case, have 2 working SAS programs).
once both programs are working correctly and producing the correct output, look at the programs carefully and decide which parts are "conditional" and which parts can stay the same for every invocation.
2) decide on the names of your macro variables and, where possible, test the programs from #1 using hard-coded macro variables with %LET statements
3) convert the conditional portions of the programs (either whole steps or partial steps or partial pieces of code) to be inside a macro program definition( %MACRO/%MEND ) -- which will DEFINE the statements or code snippets that you want to send to the compiler when the macro is invoked and the macro statements are resolved.
4) test the new macro program and the macro conditional logic in that macro program by invoking the macro program defined in #3. The name of the macro program is what came after the %MACRO keyword in #3.

Here's an example of what I mean.
1) Here are my 2 working SAS programs:
[pre]
** step #1;
data newfile;
set sashelp.class(keep=name sex age height);
if sex = "M";
run;

proc print data=newfile;
title 'Newfile from sashelp.class';
run;

data newfile2;
set sashelp.shoes(keep=region product sales);
if region = "Canada";
run;

proc print data=newfile2;
title 'Newfile2 from sashelp.shoes';
run;

[/pre]

And I decide that I am going to call my macro variables &WANT and &KEEPLIST.

So, my #2 version (without the PROC PRINTS) of the program looks like this:
[pre]

%let want = M;
%let keeplist = "name sex age height";
data newfile;
set sashelp.class(keep=&keeplist);
if sex = "&want";
run;

** proc print step;

%let want = Canada;
%let keeplist = "region product sales";

data newfile2;
set sashelp.shoes(keep=&keeplist);
if region = "&want";
run;

** proc print step;
[/pre]

I also decide that my macro program will just generate the SET statement and the IF statement that I need to select the records.

My macro definition looks like this and at this point I want to add some error processing to the macro definition:
[pre]
** step #3 DEFINE the macro program;

%macro choose(want=, keeplist=);

%If &want=M %then %do;
set sashelp.class(keep=&keeplist);
if sex = "&want";
%end;
%else %if &want = Canada %then %do;
set sashelp.shoes(keep=&keeplist);
if region = "&want";
%end;
%else %do;
data _null_;
file print;
title '3) Error Message';
put '----- ----- ----- ----- -----';
put "You did not choose M or Canada as the value you wanted";
put "You chose WANT=&WANT and KEEPLIST=&KEEPLIST ";
put "Please reinvoke the macro with the correct choices";
put '----- ----- ----- ----- -----';
run;
%end;
%mend choose;
[/pre]

In #3, I DEFINED the macro program CHOOSE. I also defined it to have some KEYWORD parameters WANT and KEEPLIST. To invoke this program, I will use the macro trigger % in front of the macro program name. So in order to test the macro program the invocation will be one of these 2 possibilities:
[pre]
%CHOOSE(want=M,keeplist=name age sex height);
%CHOOSE(want=Canada,keeplist=region product sales);
[/pre]
But I also need to invoke the macro for all conditions, including the error condition, and examine the output. And, since my macro program does NOT generate a full data step, but only generates code snippets, I have to invoke the macro in the right way (inside a DATA step program) as shown in #4 below:
[pre]

** step #4 test the macro defined above;
ods listing;
** 1) test want=M should use sashelp.class;
data newfile;
%choose(want=M, keeplist=name sex age height);
run;

proc print data=newfile;
title '1) Use Macro first time';
run;

** 2) test want=Canada should use sashelp.shoes;
data newfile2;
%choose(want=Canada, keeplist=region product sales);
run;

proc print data=newfile2;
title '2) Use Macro second time';
run;

** 3) test macro with value not allowed;
data newfile3;
%choose(want=Pacific, keeplist=region subsidiary sales);
run;

proc print data=newfile3;
title '3) Use Macro third time';
run;

[/pre]

The Macro definition program is like a typewriter. You pass parameters to the typewriter when you invoke the macro program and the macro program automatically types the right SET and IF statement -- before the statements are compiled, so the compiler NEVER sees the wrong statement.

(Note how inside macro conditional logic %IF/%DO, I do not use any quotes when I test the values for &WANT -- this is because the macro processor knows that it's just dealing with text strings -- so inside the macro conditional logic, quotes are unnecessary. BUT, inside the data step program, where I want the resolved value of &WANT to be compared to a data set variable, I have to use quotes appropriately in the data step logic.)

So your question was -- Is it possible to use a DO statement when selecting my data sets-- the answer is yes -- but there are multiple ways of doing it. IF you want to stick with DATA step logic, there IS a way to make it work, but I don't normally recommend using DATA step logic to generate code snippets. As my dad used to say, in for a dime, in for a dollar -- which to me means that since you are already using macro variables (in for a dime) and IF you want to conditionally compile and execute code snippets, then you may as well use macro conditional logic to generate your code snippets (in for a dollar).

This is my "never fail" method for developing macros and implementing conditional logic.

cynthia
N/A
Posts: 0

Re: IF then DO to select your data sets

Thanx for the help. I am fairly new to SAS coding so I am trying to impliment the pieces that you have provided.
SAS Super FREQ
Posts: 8,819

Re: IF then DO to select your data sets

Hi:
I assume that you have some programming experience or have taken some programming classes. There is a difference between DATA step statements and Macro program statements. The documentation for the SAS Macro facility is quite thorough and has many good examples.

In addition, if you search for SUGI or SAS Global Forum papers by Googling:
SAS SUGI Data Step beginners
SAS SGF Data Step beginners
SAS Macro beginners

...you should find some hits to papers which may help you get started. If you are truly new to SAS, then I definitely recommend a conservative approach to program development and make sure you understand what is happening at each step along the way before you move to the next step.

In addition, you can search SAS publishing for books by users, especially those written by Art Carpenter or Michelle Burlew -- both of whom have written books on the SAS Macro facility.

And, last, but not least, there are a number of SAS classes on programming and macro processing that you can take.

Have fun! Remember, the macro facility is a text generator -- ALL it is doing is building code before the code goes to the compiler. That means you MUST, MUST, MUST have a good idea of what correct, working code looks like before you attempt to implement macro conditional logic. But, the investment of "learning time" is really worth the effort. The SAS macro facility is LOTS of fun and the ways you can generate customized, data-driven code go from the really simple to the really complex. Totally cool.

cynthia
N/A
Posts: 0

Re: IF then DO to select your data sets

What you want to do will work.

The problem you were having was due to what a macro variable is, and when it takes affect/effect.

%let dummy = nothing;

DATA dummy;
if &dummy = "dummy" then do:
dummy = 1;
end;
run;
quit;

When SAS compiles the DATA step, the value for &dummy is substituted at that time producing:

DATA dummy;
if nothing = "dummy" then do;
dummy = 1;
end;
run;
quit;

nothing will then be interpreted as a variable name, not a string, and ...

So, to get what you wanted:

DATA dummy;
if "&dummy" = "dummy" then do;
dummy = 1;
end;
run;
quit;

Now the IF statement will test IF "nothing" = "dummy" then do; ...
N/A
Posts: 0

Re: IF then DO to select your data sets

But, it would be more elegant to use a macro;

%macro select_set(selection);

%if "&selection" = "PortfolioDaily" %then %do;
SET port.dlscad (KEEP= &keeplist5)
port.secdcad (KEEP= &keeplist3)
port.dlscbna (KEEP= &keeplist5)
port.secdcbna (KEEP= &keeplist3);
%end;
%else %do;
SET pmport.dlscad1 (KEEP= &keeplist5)
pmport.secdcad1 (KEEP= &keeplist3)
pmport.dlscbna1 (KEEP= &keeplist5)
pmport.secdcbna1 (KEEP= &keeplist3);
%end;
%mend;

DATA test;
%select_set(&cScenario);
run;
quit;
Ask a Question
Discussion stats
  • 5 replies
  • 408 views
  • 0 likes
  • 2 in conversation