Help using Base SAS procedures

Why does SAS truncate macro not work?

Reply
Contributor
Posts: 21

Why does SAS truncate macro not work?

Hi,

 

I am trying to invoke a macro I have. I have already run it. It looks like this. 

 

%macro truncate(dsetin=, dsetout=, var=);

proc sort data=&dsetin out=rank&var;
by &var;
run;

proc rank data=rank&var out=test&var groups=100;
var &var;
ranks q&var;
run;

data &dsetout;
set test&var;
if q&var = 0 or q&var = 99 then delete;
run;
proc sort data=&dsetout;
by fyear gvkey;
run;

%mend truncate;

 

When I invoke it into my program it gives me this error or does not give an error but also does not produce the data set. I am trying to truncate 1% and 99% of certain variables.

 

Thank you!

 

512 %truncate(comp_ret, comp_ret1, NI_price_tm1 NI_AT_tm1 cumret)
ERROR: More positional parameters found than defined.

513 %truncate(comp_ret, comp_ret1, NI_price_tm1)
ERROR: More positional parameters found than defined.

514 %truncate(comp_ret,comp_ret1,NI_price_tm1)
ERROR: More positional parameters found than defined.

515 %truncate(comp_ret,comp_ret1,NI_price_tm1);
ERROR: More positional parameters found than defined.

516 %macro truncate(dsetin=, dsetout=, var=);
517
518 proc sort data=&dsetin out=rank&var;
519 by &var;
520 run;
521
522 proc rank data=rank&var out=test&var groups=100;
523 var &var;
524 ranks q&var;
525 run;
526
527 data &dsetout;
528 set test&var;
529 if q&var = 0 or q&var = 99 then delete;
530 run;
531 proc sort data=&dsetout;
532 by fyear gvkey;
533 run;
534
535 %mend truncate;

536 %truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1;
537 %truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1);
ERROR: More positional parameters found than defined.
538

Super User
Posts: 3,918

Re: Why does SAS truncate macro not work?

[ Edited ]
%macro truncate(dsetin=, dsetout=, var=);

proc sort data=&dsetin out=rank&var;
by &var;
run;

proc rank data=rank&var out=test&var groups=100;
var &var;
ranks q&var;
run;

data &dsetout;
set test&var;
if q&var = 0 or q&var = 99 then delete;
run;
proc sort data=&dsetout;
by fyear gvkey;
run;

%mend truncate;

%truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1 NI_AT_tm1 cumret);

You are mixing up positional and named parameters. You just need to stick with the named parameters as in the first version of your macro.

Super User
Posts: 23,724

Re: Why does SAS truncate macro not work?

[ Edited ]

Your macro isn't designed to properly account for multiple variables at once. 

At least that's one issue, see below, I'm sure you can see how that's not valid SAS syntax. 

 

So you specified VAR as: NI_price_tm1 NI_AT_tm1 cumret


The macro processor, literally does text replacement so this is what you're submitting:

 

proc sort data=&dsetin out=rankNI_price_tm1 NI_AT_tm1 cumret;
by NI_price_tm1 NI_AT_tm1 cumret;
run;
proc rank data=rankNI_price_tm1 NI_AT_tm1 cumret out=testNI_price_tm1 NI_AT_tm1 cumret groups=100;
var NI_price_tm1 NI_AT_tm1 cumret;
ranks qNI_price_tm1 NI_AT_tm1 cumret;
run;

 

 

The error you're currently getting is not because of the issue above, though, or at least not fully. It's because you're not using the = sign. If you call the macro as follows your initial error will go away, but you'll have other errors because of the issue I pointed out:

 

%truncate(dsetin=sashelp.cars, dsetout=cars, var=mpg_highway mpg_city);

 

You may want to modify your macro to take a different parameter somehow, since I assume you don't really want a new dataset for each variable. 

 

I have one I wrote a while back here, just updated it on GitHub to include the .sas extension for formatting. I think its what you're trying to do. Feel free to use as desired. 

 

https://gist.github.com/statgeek/7cffd06ebc3bc9c78b4f6a5b4538b053

 

Spoiler

dlazer1 wrote:

Hi,

 

I am trying to invoke a macro I have. I have already run it. It looks like this. 

 

%macro truncate(dsetin=, dsetout=, var=);

proc sort data=&dsetin out=rank&var;
by &var;
run;

proc rank data=rank&var out=test&var groups=100;
var &var;
ranks q&var;
run;

data &dsetout;
set test&var;
if q&var = 0 or q&var = 99 then delete;
run;
proc sort data=&dsetout;
by fyear gvkey;
run;

%mend truncate;

 

When I invoke it into my program it gives me this error or does not give an error but also does not produce the data set. I am trying to truncate 1% and 99% of certain variables.

 

Thank you!

 

512 %truncate(comp_ret, comp_ret1, NI_price_tm1 NI_AT_tm1 cumret)
ERROR: More positional parameters found than defined.

513 %truncate(comp_ret, comp_ret1, NI_price_tm1)
ERROR: More positional parameters found than defined.

514 %truncate(comp_ret,comp_ret1,NI_price_tm1)
ERROR: More positional parameters found than defined.

515 %truncate(comp_ret,comp_ret1,NI_price_tm1);
ERROR: More positional parameters found than defined.

516 %macro truncate(dsetin=, dsetout=, var=);
517
518 proc sort data=&dsetin out=rank&var;
519 by &var;
520 run;
521
522 proc rank data=rank&var out=test&var groups=100;
523 var &var;
524 ranks q&var;
525 run;
526
527 data &dsetout;
528 set test&var;
529 if q&var = 0 or q&var = 99 then delete;
530 run;
531 proc sort data=&dsetout;
532 by fyear gvkey;
533 run;
534
535 %mend truncate;

536 %truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1;
537 %truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1);
ERROR: More positional parameters found than defined.
538


Super User
Super User
Posts: 8,107

Re: Why does SAS truncate macro not work?

If you define the parameters as named rather than positional then you must call them using the parameter names.

Also your first attempt to call it using positional parameters is missing the closing right parenthesis so the second attempt with using named values in the call never got noticed as an actual call to the macro.

 

 

So either change your macro definition to allow positional calls.

%macro truncate(dsetin, dsetout, var);

Or make sure your macro call is using the names.

%truncate(dsetin=comp_ret, dsetout=comp_ret1, var=NI_price_tm1);

Or do BOTH.  Even if you define the macro parameter to accept values by position, you can still call the macro using the names for those parameters..

 

Trusted Advisor
Posts: 1,337

Re: Why does SAS truncate macro not work?

You are apparently trying to winsorize your data on 3 variables: NI_price_tm1, NI_AT_tm1, and cumret.  It's not clear whether these are to be winsorized simultaneously over the three variables, or stepwise.  Let me assume the earlier.  Your program would need to look like this:

 

proc rank data=have groups=100  out=need ;
  vars NI_price_tm1 NI_AT_tm1 cumret;
  ranks q_NI_price_tm1 q_NI_AT_tm1 q_cumret;
run;
proc sort data=need out=want;
  by fyear gvkey ;
where min(q_ni_price_tm1,q_ni_at_tm1,q_cumret)>0
and max(q_ni_price_tm1,q_ni_at_tm1,q_cumret)<99;
run;

 

The point is the you don't need the preceding sort if your are not ranking within by groups.  Also you can winsorize the output data set NEED during the sort that follows ranking.

 

To macroize:

%macro truncate (dsin=,dsout=,vars=,rnks=,csrnks=);
proc rank data=&dsin out=need groups=100 ;
  var &vars;
  ranks &rnks;
run;

proc sort data=need out=&dsout;
  by x y;
  where min(%unquote(&csrnks))>0
	and max(%unquote(&csrnks))<99;
run;
%mend;
options mprint;
%truncate(dsin=have,dsout=want,vars=ni_price_tm1 ni_at_tm1 cumret
          ,rnks=pctl_ni_price_tm1 pctl_ni_at_tm1 pctl_cumret
          ,csrnks=pctl_ni_price_tm1%str(,)pctl_ni_at_tm1%str(,)pctl_cumret
         );

I added a couple arguments to your macro:  RNKS, a list of percentile variables you intend to create for VARS, and CSRNKS (comma-separated ranks).  CSRNKS repeats the RNKS macrovar, but uses a %str(,) where you plan to have a comma INSIDE a macrovar.  Using %str() in the argument specification prevents it from being interpreted as a separator in the macro definition.   But you'll notice that references to CSRNKS inside the macro now have to be embedded in an %UNQUOTE() macro function.

 

Ask a Question
Discussion stats
  • 4 replies
  • 212 views
  • 0 likes
  • 5 in conversation