BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
finans_sas
Quartz | Level 8

Hello Everyone:

I am working with a SAS macro to winsorize my data (please see attached). The SAS macro is below. When I run the program, it appears to be running okay (no error is generated), however there is no output. Could you help me identify what might be the problem? I tried closing the SAS program and opening back again, but it did not help.

Thank you so much!

 

/*******************************************************************************
http://www.byuaccounting.net/mediawiki/images/5/51/WinsorizeMacro.txt
Winsorize macro
Can winsorize or trim at specified percentiles;
dsetout = leave blank to overwrite dsetin
byvar = none for no byvar (trims/winsorizes pooled sample)
type = delete/winsor
ex: %winsor(dsetin=mydata, dsetout=mydata2, byvar=year, vars=assets earnings, pctl=0 98);
winsorizes by year at 98%, puts resulting dataset into mydata2

%winsor(dsetin=mydata, vars=assets earnings, type=delete);
trims pooled sample at 1% and 99%, puts resulting dataset back into mydata
********************************************************************************/

%macro winsor(dsetin=sasregrr, dsetout=aregrr, byvar=none, vars=equal, type=winsor, pctl=15 85);

%if &dsetout = %then %let dsetout = &dsetin;

%let varL=;
%let varH=;
%let xn=1;

%do %until ( %scan(&vars,&xn)= );
%let token = %scan(&vars,&xn);
%let varL = &varL &token.L;
%let varH = &varH &token.H;
%let xn=%EVAL(&xn + 1);
%end;

%let xn=%eval(&xn-1);

data xtemp;
set &dsetin;
run;

%let dropvar = ;
%if &byvar = none %then %do;

data xtemp;
set xtemp;
xbyvar = 1;
run;

%let byvar = xbyvar;
%let dropvar = xbyvar;

%end;

proc sort data = xtemp;
by &byvar;
run;

proc univariate data = xtemp noprint;
by &byvar;
var &vars;
output out = xtemp_pctl PCTLPTS = &pctl PCTLPRE = &vars PCTLNAME = L H;
run;

data &dsetout;
merge xtemp xtemp_pctl;
by &byvar;
array trimvars{&xn} &vars;
array trimvarl{&xn} &varL;
array trimvarh{&xn} &varH;

do xi = 1 to dim(trimvars);

%if &type = winsor %then %do;
if trimvars{xi} ne . then do;
if (trimvars{xi} < trimvarl{xi}) then trimvars{xi} = trimvarl{xi};
if (trimvars{xi} > trimvarh{xi}) then trimvars{xi} = trimvarh{xi};
end;
%end;

%else %do;
if trimvars{xi} ne . then do;
if (trimvars{xi} < trimvarl{xi}) then delete;
if (trimvars{xi} > trimvarh{xi}) then delete;
end;
%end;

end;
drop &varL &varH &dropvar xi;
run;


%mend winsor;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User

Well, you still never called the macro. Did you read the instructions at the top of the program? You don't put the parameters in the %MACRO statement, you put them in a call after the macro definition.

Here's a different example. Make sure you use the original macro code not your modified %macro statement.

Macro definition (portion of code you have shown)

%macro print(dsn=);
proc print data=&dsn.;
run;
%mend;


Macro call/execution - THE PART YOU'RE MISSING:

%print(sashelp.class);



View solution in original post

4 REPLIES 4
Reeza
Super User

Please show your macro call and the log. Below, you've shown the macro code but no actual attempt to use it. 

 

To use the macro I'd expect to see something like the following in your code (from header instructions)

 

%winsor(dsetin=mydata, vars=assets earnings, type=delete);
Spoiler

@finans_sas wrote:

Hello Everyone:

I am working with a SAS macro to winsorize my data (please see attached). The SAS macro is below. When I run the program, it appears to be running okay (no error is generated), however there is no output. Could you help me identify what might be the problem? I tried closing the SAS program and opening back again, but it did not help.

Thank you so much!

 

/*******************************************************************************
http://www.byuaccounting.net/mediawiki/images/5/51/WinsorizeMacro.txt
Winsorize macro
Can winsorize or trim at specified percentiles;
dsetout = leave blank to overwrite dsetin
byvar = none for no byvar (trims/winsorizes pooled sample)
type = delete/winsor
ex: %winsor(dsetin=mydata, dsetout=mydata2, byvar=year, vars=assets earnings, pctl=0 98);
winsorizes by year at 98%, puts resulting dataset into mydata2

%winsor(dsetin=mydata, vars=assets earnings, type=delete);
trims pooled sample at 1% and 99%, puts resulting dataset back into mydata
********************************************************************************/

%macro winsor(dsetin=sasregrr, dsetout=aregrr, byvar=none, vars=equal, type=winsor, pctl=15 85);

%if &dsetout = %then %let dsetout = &dsetin;

%let varL=;
%let varH=;
%let xn=1;

%do %until ( %scan(&vars,&xn)= );
%let token = %scan(&vars,&xn);
%let varL = &varL &token.L;
%let varH = &varH &token.H;
%let xn=%EVAL(&xn + 1);
%end;

%let xn=%eval(&xn-1);

data xtemp;
set &dsetin;
run;

%let dropvar = ;
%if &byvar = none %then %do;

data xtemp;
set xtemp;
xbyvar = 1;
run;

%let byvar = xbyvar;
%let dropvar = xbyvar;

%end;

proc sort data = xtemp;
by &byvar;
run;

proc univariate data = xtemp noprint;
by &byvar;
var &vars;
output out = xtemp_pctl PCTLPTS = &pctl PCTLPRE = &vars PCTLNAME = L H;
run;

data &dsetout;
merge xtemp xtemp_pctl;
by &byvar;
array trimvars{&xn} &vars;
array trimvarl{&xn} &varL;
array trimvarh{&xn} &varH;

do xi = 1 to dim(trimvars);

%if &type = winsor %then %do;
if trimvars{xi} ne . then do;
if (trimvars{xi} < trimvarl{xi}) then trimvars{xi} = trimvarl{xi};
if (trimvars{xi} > trimvarh{xi}) then trimvars{xi} = trimvarh{xi};
end;
%end;

%else %do;
if trimvars{xi} ne . then do;
if (trimvars{xi} < trimvarl{xi}) then delete;
if (trimvars{xi} > trimvarh{xi}) then delete;
end;
%end;

end;
drop &varL &varH &dropvar xi;
run;


%mend winsor;

 

 


finans_sas
Quartz | Level 8

Thank you so much @Reeza for your quick reply. I copied and pasted what I saw on the log (I am so sorry for all these numbers showing up on the left). Please let me know if I can provide any further information. I also attached the SAS program file to this reply.

Thank you

 

4652 %macro winsor(dsetin=sasregrr, dsetout=aregrr, byvar=none, vars=equal, type=winsor, pctl=15
4652! 85);
4653
4654 %if &dsetout = %then %let dsetout = &dsetin;
4655
4656 %let varL=;
4657 %let varH=;
4658 %let xn=1;
4659
4660 %do %until ( %scan(&vars,&xn)= );
4661 %let token = %scan(&vars,&xn);
4662 %let varL = &varL &token.L;
4663 %let varH = &varH &token.H;
4664 %let xn=%EVAL(&xn + 1);
4665 %end;
4666
4667 %let xn=%eval(&xn-1);
4668
4669 data xtemp;
4670 set &dsetin;
4671 run;
4672
4673 %let dropvar = ;
4674 %if &byvar = none %then %do;
4675
4676 data xtemp;
4677 set xtemp;
4678 xbyvar = 1;
4679 run;
4680
4681 %let byvar = xbyvar;
4682 %let dropvar = xbyvar;
4683
4684 %end;
4685
4686 proc sort data = xtemp;
4687 by &byvar;
4688 run;
4689
4690 proc univariate data = xtemp noprint;
4691 by &byvar;
4692 var &vars;
4693 output out = xtemp_pctl PCTLPTS = &pctl PCTLPRE = &vars PCTLNAME = L H;
4694 run;
4695
4696 data &dsetout;
4697 merge xtemp xtemp_pctl;
4698 by &byvar;
4699 array trimvars{&xn} &vars;
4700 array trimvarl{&xn} &varL;
4701 array trimvarh{&xn} &varH;
4702
4703 do xi = 1 to dim(trimvars);
4704
4705 %if &type = winsor %then %do;
4706 if trimvars{xi} ne . then do;
4707 if (trimvars{xi} < trimvarl{xi}) then trimvars{xi} = trimvarl{xi};
4708 if (trimvars{xi} > trimvarh{xi}) then trimvars{xi} = trimvarh{xi};
4709 end;
4710 %end;
4711
4712 %else %do;
4713 if trimvars{xi} ne . then do;
4714 if (trimvars{xi} < trimvarl{xi}) then delete;
4715 if (trimvars{xi} > trimvarh{xi}) then delete;
4716 end;
4717 %end;
4718
4719 end;
4720 drop &varL &varH &dropvar xi;
4721 run;
4722
4723
4724 %mend winsor;

 

Reeza
Super User

Well, you still never called the macro. Did you read the instructions at the top of the program? You don't put the parameters in the %MACRO statement, you put them in a call after the macro definition.

Here's a different example. Make sure you use the original macro code not your modified %macro statement.

Macro definition (portion of code you have shown)

%macro print(dsn=);
proc print data=&dsn.;
run;
%mend;


Macro call/execution - THE PART YOU'RE MISSING:

%print(sashelp.class);



finans_sas
Quartz | Level 8
Thank you so much, Reeza!

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 1955 views
  • 0 likes
  • 2 in conversation