Hi,
can the below code be written in small and efficient way.basically can we eliminate the repetitive code.
data test2;
set test;
if freq='M' then
do;
date1=canceldate;
days2=intnx('month',date1,1)-intnx('month',date1,0);
if days < days2 then
do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
end;
else if freq='H' then
do;
date1=canceldate;
days2=intnx('month',date1,6)-intnx('month',date1,0);
if days < days2 then
do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
end;
else if freq='Q' then
do;
date1=canceldate;
days2=intnx('month',date1,3)-intnx('month',date1,0);
if days < days2 then
do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
end;
else if freq='F' then
do;
date1=canceldate;
days2=intnx('week',date1,2)-intnx('week',date1,0);
if days < days2 then
do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
end;
run;
You have 'week' as the designated interval for FREQ='F', and month for the other listed FREQ values. So you have to change two parameters in the intnx function.
Also, there is no need within the code you submitted to generate date1, since canceldate can be used in the function calls:
Below is untested in the absence of sample data:
data test2 (drop=_:);
set test;
if freq in ('M','H','Q','F') then do;
_parm2=index('MFQ..H',freq); /* M->1, F->2, Q->3, H->6 */
_parm1='month';
if freq='F' then _parm1='week';
end;
days2=intnx(_parm1,canceldate,_parm2,0);
if days < days2 then do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
run;
It looks as if the only thing that is changing is the 3rd argument of INTNX. (By the way, you should just come out and say that — tell us what you know — rather than expecting someone to figure that out and possibly get it wrong ... did I miss any other areas of code that is changing?)
data test2;
set test;
if freq='M' then parm=1;
else if freq='H' then parm=6;
else if freq='Q' then parm=3;
else if freq='F' then parm=2;
date1=canceldate;
days2=intnx('month',date1,parm)-intnx('month',date1,0);
if days < days2 then do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
run;
One issue in producing an equivalent program is this. Is FREQ guaranteed to always be "M", "J", "Q", or "F"? If so, @PaigeMiller 's suggestion is ideal. If not (for example, if FREQ is sometimes missing), you might want to modify it slightly:
data test2;
set test;
if freq='M' then parm=1;
else if freq='H' then parm=6;
else if freq='Q' then parm=3;
else if freq='F' then parm=2;
if freq in ('M', 'H', 'Q', 'F') then do;
date1=canceldate;
days2=intnx('month',date1,parm)-intnx('month',date1,0);
if days < days2 then do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
end;
run;
Not sure if this performs better than the suggested solutions (code is not tested):
proc format;
invalue freq2num
'M' = 1
'H' = 6
'Q' = 3
'F' = 2
other = .;
run;
data want;
set have;
date1=canceldate;
days2=intnx('month',date1,input(freq, freq2num.)) - intnx('month',date1,0);
if days < days2 then do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
run;
You have 'week' as the designated interval for FREQ='F', and month for the other listed FREQ values. So you have to change two parameters in the intnx function.
Also, there is no need within the code you submitted to generate date1, since canceldate can be used in the function calls:
Below is untested in the absence of sample data:
data test2 (drop=_:);
set test;
if freq in ('M','H','Q','F') then do;
_parm2=index('MFQ..H',freq); /* M->1, F->2, Q->3, H->6 */
_parm1='month';
if freq='F' then _parm1='week';
end;
days2=intnx(_parm1,canceldate,_parm2,0);
if days < days2 then do;
prem=round(days/days2*prem1,0.01);
calc=round(days/days2*calc1,0.01);
end;
run;
Editted comment. Just realized that I submitted this response twice, so I'm striking out the entire content below:
It looks like you want WEEK interval for FREQ=-'F' and MONTH for the others. So you have to modify two parameters of the INTNX function.
Also there is no apparent need for the DATE1 variable in you code, since CANCELDATE is identical.
The code below is untested:
data test2 (drop=_:); set test; if freq in ('M','H','Q','F') then do; _parm2=index('MFQ..H',freq); /* M->1, F->2, Q->3, H->6 */ _parm1='month'; if freq='F' then _parm1='week'; end; days2=intnx(_parm1,canceldate,_parm2,0); if days < days2 then do; prem=round(days/days2*prem1,0.01); calc=round(days/days2*calc1,0.01); end; run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.