Help using Base SAS procedures

Dynamic Macro Variables

Reply
Contributor
Posts: 59

Dynamic Macro Variables

Hi,

I am trying to figure out a way to do this for quite some time, but have no luck

I have a variable RSCORE which will take values like below

1 3 4 5 6 9 10 11
As you can notice it will not be in sequence. Based on these values I am defining Dynamic Macro variables. Please refer to code below
do i = RSCORE;
if RSCORE = (i) then do;
call symput ('MIN'||compress(i),compress(MINSCORE));
call symput ('RSCORE'||compress(i),compress(RSCORE));
call symput ('MAX'||compress(i),compress(MAXSCORE));

I need to use the Max and Min in particular Ranges of RSCORE on another variable in another dataset.
Something like if &&MIN&i.<=scr<=&&MAX&i. then RSCORE1 = &&RSCORE&i.; However I am not sure how to define the above %DO loop before that statement as RSCORE doesnt takes vales sequentially.Not sure if someone has done this before, would be very helpful if you can share anything.
Thanks

Message was edited by: tejeshwar

Tejeshwar

Message was edited by: tejeshwar Message was edited by: tejeshwar
Super Contributor
Super Contributor
Posts: 3,174

Re: Dynamic Macro Variables

Please show what the resulting "generated" SAS code should look like, please? Also, if you code the following statement in your SAS program, you can identify what is being generated by your SYMPUT code -- consider exploring the use of SYMPUTX to help abbreviate your CALL statement, also.

%PUT >INFO> SAS GLOBAL VARIABLES LISTED BELOW:
%PUT _GLOBAL_;

And be sure to code a RUN; statement at the end of your DATA step, due to SAS rules for macro variable scope with SYMPUT/SYMPUTX.

Scott Barry
SBBWorks, Inc.
Contributor
Posts: 59

Re: Dynamic Macro Variables

DATA ALL3;
SET ALL2;
format RANGE $9.;

if RSCORE = . then do; RSCORE1 = 'MISSING';RANGE = 'MISSING';
end;
else do;
do i = RSCORE;
if RSCORE = (i) then do;
call symput ('MIN'||compress(i),compress(MINSCORE));
call symput ('RSCORE'||compress(i),compress(RSCORE));
call symput ('MAX'||compress(i),compress(MAXSCORE));
RSCORE1 = RSCORE;
RANGE = compress(MINSCORE||"-"||MAXSCORE);
end;
end;
end;
rename _FREQ_ = F;
run;
%PUT _GLOBAL_;

This is the log
_________________
77 %PUT _GLOBAL_;
GLOBAL MIN0 101
GLOBAL MIN1 104
GLOBAL MAX0 103
GLOBAL MIN2 210
GLOBAL MAX1 203
GLOBAL MIN3 402
GLOBAL MAX2 401
GLOBAL MIN4 503
GLOBAL MAX3 502
GLOBAL MIN5 701
GLOBAL MAX4 603
GLOBAL MIN6 802
GLOBAL RSCORE3 3
GLOBAL MAX5 801
GLOBAL MIN7 903
GLOBAL RSCORE2 2
GLOBAL MAX6 902
GLOBAL RSCORE1 1
GLOBAL MAX7 1003
GLOBAL RSCORE0 0
GLOBAL RSCORE7 7
GLOBAL RSCORE6 6
GLOBAL RSCORE5 5
GLOBAL RSCORE4 4

There is another Dataset which will have a variable score where I will need t define the RSCORE for between a range
ex: if &MIN0.<=scr<=&&MAX0. then RSCORE1 = &RSCORE.
else if &MIN1.<=scr<=&&MAX1. then RSCORE1 = &RSCORE
and so on.
I was hoping If I could acomplish this inposition in a manner where it isnt dependent on me knowing the ranges and the dynamic varaiables thatget created based on values of RSCORE.
Thanks
Super Contributor
Super Contributor
Posts: 3,174

Re: Dynamic Macro Variables

It's unclear exactly what you want the result to be data-wise. Please share a specific sample if input values, explain in words the processing logic flow, and then show the expected output values.

Scott Barry
SBBWorks, Inc.
Contributor
Posts: 59

Re: Dynamic Macro Variables

Hi,

Apologies if I was unclear.
Lets say I have a data which has some scores like 101, 102, 103,104,201,203,204.

Post this I did a Proc Rank to make 10 deciles and look at the distribution.
Code-
PROC RANK DATA=all (keep = scr ) OUT=all1 (keep = scr RSCORE) GROUPS=10 ;
VAR scr;
RANKS RSCORE;
RUN;

Post this I need to define a range that a particular deciles takes, so have done
Code-
PROC MEANS DATA=ALL1 NOPRINT;
VAR scr ;
BY RSCORE ;
OUTPUT OUT=ALL2
MIN=MINSCORE MAX=MAXSCORE ;

RUN;

DATA ALL3;
SET ALL2;
format RANGE $9.;

if RSCORE = . then do; RSCORE1 = 'MISSING';RANGE = 'MISSING';
end;
else do;
do i = RSCORE;
if RSCORE = (i) then do;
call symput ('MIN'||compress(i),compress(MINSCORE));
call symput ('RSCORE'||compress(i),compress(RSCORE));
call symput ('MAX'||compress(i),compress(MAXSCORE));
RSCORE1 = RSCORE;
RANGE = compress(MINSCORE||"-"||MAXSCORE);
end;
end;
end;
rename _FREQ_ = F;
run;
%PUT _GLOBAL_;

Once I have the range of each decile, I was hoping to impose that on same variable, however the source and data is different. The objective is to compare the distribution within deciles for these 2 sources.

So possibly I was hoping to define the deciles manually on the other dataset through the max and min macro variables that have been generated above and then use a proc sql to get the count for each range.

So I am stuck at a point where I am trying to figure out the way to impose the range on new data with &Max and &Min (these will be dynamic based on deciles that gets created and remember we might not get exact same ranks as we mentioned, since at times the 2 deciles are grouped withing one.

Regards,
Tejeshwar Message was edited by: tejeshwar
Contributor
Posts: 59

Re: Dynamic Macro Variables

As of now on the other dataset I have referencing the variables created above in below manner.
if &MIN0. le scr le &MAX0. then DECILE = &RSCORE0.;
else if &MIN1. le scr le &MAX1. then DECILE = &RSCORE1.;
else if &MIN2. le scr le &MAX2. then DECILE = &RSCORE2.;
else if &MIN3. le scr le &MAX3. then DECILE = &RSCORE3.;
else if &MIN4. le scr le &MAX4. then DECILE = &RSCORE4.;
else if &MIN5. le scr le &MAX5. then DECILE = &RSCORE5.;
else if &MIN6. le scr le &MAX6. then DECILE = &RSCORE6.;
else if &MIN7. le scr le &MAX7. then DECILE = &RSCORE7.;
else if &MIN8. le scr le &MAX8. then DECILE = &RSCORE8.;
else if &MIN9. le scr le &MAX9. then DECILE = &RSCORE9.);
run;

but this is dependent on me knowing exactly the Macro variables that gets created above. Doing a do loop from 0 TO 9 might not wrk if Proc Rank clubs 2 deciles into 1.
Super Contributor
Super Contributor
Posts: 3,174

Re: Dynamic Macro Variables

Investigate the use of a PROC FORMAT to generate a numeric SAS format for look-up and assignment, based on the data-ranges you will have for SCR and the output values you want to have for RSCORE. A DATA step would be used to assign RSCORE with the PUT function in a SAS assignment statement.

Search the SAS support http://support.sas.com/ website for technical conference papers on phrases "proc format" and "put function" and "look up" using either the SAS website's SEARCH command or by doing a Google advanced search against the SAS.COM site -- accomplished with using the site:sas.com keyword.

Scott Barry
SBBWorks, Inc.
PROC Star
Posts: 1,562

Re: Dynamic Macro Variables

Yes, you need formats, like:
[pre]
proc rank data=SASHELP.CITIDAY out=ALL1(keep=DFXWUK90 RSCORE) groups=10 ;
var DFXWUK90;
ranks RSCORE;
proc means data=ALL1 noprint nway;
var DFXWUK90;
class RSCORE ;
output out=ALL2 min=MIN max=MAX;
data FORMAT;
retain FMTNAME 'decile' TYPE 'N';
set ALL2(rename=(MIN=START MAX=END RSCORE=LABEL));
proc format cntlin=FORMAT;
data _null_;
set SASHELP.CITIDAY(where=( '01mar1990'd <= DATE <= '31mar1990'd));
V2=put(SNYSECM,decile2.);
put V2=;
run;[pre]
You might want to enhance the FORMAT table to take care of values outside the deciles range ( variable HLO).

Message was edited by: C. Graffeuille Message was edited by: C. Graffeuille
Ask a Question
Discussion stats
  • 7 replies
  • 215 views
  • 0 likes
  • 3 in conversation