BookmarkSubscribeRSS Feed
dlazer1
Calcite | Level 5

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

4 REPLIES 4
SASKiwi
PROC Star
%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.

Reeza
Super User

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


Tom
Super User Tom
Super User

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..

 

mkeintz
PROC Star

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.

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1054 views
  • 0 likes
  • 5 in conversation