DATA Step, Macro, Functions and more

IF THEN DO alternative

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 12
Accepted Solution

IF THEN DO alternative

I'm using PC SAS v9.3.  I have some conditional logic that looks like this...

 

DATA CPA_PST(KEEP=REG LCD VARPST MEANPOST MOS);

SET CPA_PST;

          IF MOS = 3 THEN DO; VARPST = VAR(OF MONS1 - MONS3); MEANPOST = MEAN(OF MONS1 - MONS3); END;

ELSE IF MOS = 4 THEN DO; VARPST = VAR(OF MONS1 - MONS4); MEANPOST = MEAN(OF MONS1 - MONS4); END;

ELSE IF MOS = 5 THEN DO; VARPST = VAR(OF MONS1 - MONS5); MEANPOST = MEAN(OF MONS1 - MONS5); END;

ELSE IF MOS = 6 THEN DO; VARPST = VAR(OF MONS1 - MONS6); MEANPOST = MEAN(OF MONS1 - MONS6); END;

ELSE IF MOS = 7 THEN DO; VARPST = VAR(OF MONS1 - MONS7); MEANPOST = MEAN(OF MONS1 - MONS7); END;

ELSE IF MOS = 8 THEN DO; VARPST = VAR(OF MONS1 - MONS8); MEANPOST = MEAN(OF MONS1 - MONS8); END;

ELSE IF MOS = 9 THEN DO; VARPST = VAR(OF MONS1 - MONS9); MEANPOST = MEAN(OF MONS1 - MONS9); END;

ELSE IF MOS = 10 THEN DO; VARPST = VAR(OF MONS1 - MONS10); MEANPOST = MEAN(OF MONS1 - MONS10); END;

ELSE IF MOS = 11 THEN DO; VARPST = VAR(OF MONS1 - MONS11); MEANPOST = MEAN(OF MONS1 - MONS11); END;

ELSE IF MOS = 12 THEN DO; VARPST = VAR(OF MONS1 - MONS12); MEANPOST = MEAN(OF MONS1 - MONS12); END;

ELSE IF MOS = 13 THEN DO; VARPST = VAR(OF MONS1 - MONS13); MEANPOST = MEAN(OF MONS1 - MONS13); END;

ELSE IF MOS = 14 THEN DO; VARPST = VAR(OF MONS1 - MONS14); MEANPOST = MEAN(OF MONS1 - MONS14); END;

ELSE IF MOS = 15 THEN DO; VARPST = VAR(OF MONS1 - MONS15); MEANPOST = MEAN(OF MONS1 - MONS15); END;

RUN;

 

However I could (and probably will) have a different max number of mons to calculate going forward.  Rather than having to manually add a line each month, is there a way to use mos as my max mons value?  I'm thinking something like this...

 

DATA CPA_PST(KEEP=REG LCD VARPST MEANPOST MOS);

SET CPA_PST;

VARPST = VAR(OF MONS1 - 'MONS'||trim(left(mos))); MEANPOST = MEAN(OF MONS1 - 'MONS'||trim(left(mos)));

RUN;

 

...but SAS has no idea what I'm talking about.  I'm just at a loss as to how to do this.  Any help is appreciated!


Accepted Solutions
Solution
‎02-22-2017 11:40 AM
Super User
Posts: 6,936

Re: IF THEN DO alternative

Ouch.

Look at the documentation of the select statement (data step language).

Your code would look like

select(mos);
  when (3) do;
    varpst = var(of mons1 - mons3);
    meanpost = mean (of mons1 - mons3);
  end;
  .........
  otherwise; /* if necessary */
end;

Next, I'd pack that into a macro:

%macro my_loop(max_mon);
data cpa (keep=reg lcd varpst meanpost mos);
set cpa_pst;
select(mos);
%do i = 3 %to &max_mon.;
  when (&i.) do;
    varpst = var(of mons1 - mons&i.);
    meanpost = mean (of mons1 - mons&i.);
  end;
%end;
  otherwise; /* if necessary */
end;
%mend;

%my_loop(15)
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers

View solution in original post


All Replies
Contributor
Posts: 44

Re: IF THEN DO alternative

so are you saying you just needed the max of Mons instead of all the existing lines (i.i 1 to 15) ?
Solution
‎02-22-2017 11:40 AM
Super User
Posts: 6,936

Re: IF THEN DO alternative

Ouch.

Look at the documentation of the select statement (data step language).

Your code would look like

select(mos);
  when (3) do;
    varpst = var(of mons1 - mons3);
    meanpost = mean (of mons1 - mons3);
  end;
  .........
  otherwise; /* if necessary */
end;

Next, I'd pack that into a macro:

%macro my_loop(max_mon);
data cpa (keep=reg lcd varpst meanpost mos);
set cpa_pst;
select(mos);
%do i = 3 %to &max_mon.;
  when (&i.) do;
    varpst = var(of mons1 - mons&i.);
    meanpost = mean (of mons1 - mons&i.);
  end;
%end;
  otherwise; /* if necessary */
end;
%mend;

%my_loop(15)
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Occasional Contributor
Posts: 12

Re: IF THEN DO alternative

Awesome!  Thanks so much.  I don't think I've used the select statement in a data step before.

SAS Super FREQ
Posts: 3,476

Re: IF THEN DO alternative

Read about the SELECT statement in the article "The SELECT statement in the SAS DATA step."

Occasional Contributor
Posts: 12

Re: IF THEN DO alternative

Will do.  Thanks!

SAS Super FREQ
Posts: 3,476

Re: IF THEN DO alternative

use the COLON to select all variables that match a specified prefix:

 


data Want;
set Have;
array Y[*] MONS: ;
meanpst = mean(of Y[*]);
varpst = var(of Y[*]);
run;
Super User
Super User
Posts: 6,500

Re: IF THEN DO alternative

[ Edited ]

Perhaps you don't need to do all of that work?

It looks to me that the variable MOS has the number of values you want to include. If the rest of the variables have missing values then the  MEAN() and VAR() statement will handle that automatically.  Try running this little test and see if there are any cases in your data where MOS is NOT the number of non-missing values in your list of data values.

data _null_;
  set CPA_PST;
  if mos ne n(of mons1-mons15) then do;
    put (mos mons1-mons15) (=);
    stop;
  end;
run;

 If not then you data step can just be this simple.

data want ;
  set cpa_pst ;
  if mos >= 3 then do;
    varpst = var(of mons1-mons15);
    meanpost=mean(of mons1-mons15);
  end;
  keep reg lcd varpst meanpost mos;
run;
☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 7 replies
  • 208 views
  • 2 likes
  • 5 in conversation