Hello all,
I am a SAS beginner, so please ignore if I made any mistakes in the code. Until now I was using excel to calculate the number of persons and person time of follow up. Now, I build a code in SAS that would give me the same output by just specifying few parameters in the macro. I need help to simplify the program and allow extended periods of follow up time. Below is what I have done:
%macro test (y1, y2,y3,rate);
data want;
ny1 = &y1*(1-&rate*0.5);
pyy1 = ny1*0.5+(&y1-ny1)*0.25;
ny2 = &y2*(1-&rate*0.5)+ ny1*(1-&rate);
pyy2 = &y2*(1-&rate*0.5)*0.5+(&y2-&y2*(1-&rate*0.5))*0.25 + ny1*(1-&rate*0.5);
ny3 = &y3*(1-&rate*0.5)+ ny2*(1-&rate);
pyy3 = &y3*(1-&rate*0.5)*0.5+(&y3-&y3*(1-&rate*0.5))*0.25 + ny2*(1-&rate*0.5);
ny4 = ny3*(1-&rate);
pyy4 = ny3*(1-&rate*0.5);
ny5 = ny4*(1-&rate);
pyy5 = ny4*(1-&rate*0.5);
run;
proc print data=want;
run;
%mend test;
%test (20,30,40, 0.06);
In the above program, ny1 is the number of persons and pyy1 is the number of person years contributed in the Year 1 . The logic for the first three years keeps changing. From the fourth year onward it remains the same formula. So, for 8th year the formula would be
ny8 = ny8*(1-&rate);
pyy8 = ny8*(1-&rate*0.5)
I have shared the code for the first five years. But I need for extended periods of time like say 15 years. How can I best simplify my program. Also, I need the output in the below format (Add Cumulative Person years):
Year | ny1 | pyy1 | Cumilative PY |
1 | 19.4 | 9.85 | 9.85 |
2 | 47.336 | 33.593 | 43.443 |
3 | 83.2958 | 65.6159 | 109.0589 |
4 | 78.2981 | 80.797 | 189.8559 |
5 | 73.6002 | 75.9491 | 265.805 |
Thank you very much for all your help!!
I think what you are looking for is a DATA step, with no macro language. I will at least try to get the concept right ... not sure about all the formulas.
data want;
input y1 y2 y3 rate;
testnum=_n_;
cumulative_py=0;
ny = y1 * (1 - rate * 0.5);
pyy = ny * 0.5 + (y1 - ny) * 0.25;
year=1;
cumulative_py + pyy;
output;
pyy = y2 * (1 - rate * 0.5) * 0.5 + (y2 - y2*(1 - rate * 0.5)) * 0.25 + ny*(1 - rate*0.5);
ny = y2 * (1 - rate * 0.5) + ny*(1 - rate);
year=2;
cumulative_py + pyy;
output;
pyy = y3 * (1-rate*0.5) * 0.5 + (y3 - y3*(1 - rate * 0.5)) * 0.25 + ny * (1 - rate * 0.5);
ny = y3 * (1-rate*0.5) + ny*(1-rate);
year=3;
cumulative_py + pyy;
output;
do year=4 to 15;
pyy = ny*(1-rate*0.5);
ny = ny * (1-rate);
cumulative_py + pyy;
output;
end;
datalines;
20 30 40 0.06
;
This gives you the right results (I hope), but lets you add many more sets of tests by adding more lines of data in the same step.
It's untested, so might need some tweaking here and there.
Computation of PYY comes before calculation of NY, since PYY uses the old NY value (before applying updates for the current year).
Have you looked into Arrays yet? That's likely your best approach.
@Tomcaty wrote:
Hello all,
I am a SAS beginner, so please ignore if I made any mistakes in the code. Until now I was using excel to calculate the number of persons and person time of follow up. Now, I build a code in SAS that would give me the same output by just specifying few parameters in the macro. I need help to simplify the program and allow extended periods of follow up time. Below is what I have done:
%macro test (y1, y2,y3,rate); data want; ny1 = &y1*(1-&rate*0.5); pyy1 = ny1*0.5+(&y1-ny1)*0.25; ny2 = &y2*(1-&rate*0.5)+ ny1*(1-&rate); pyy2 = &y2*(1-&rate*0.5)*0.5+(&y2-&y2*(1-&rate*0.5))*0.25 + ny1*(1-&rate*0.5); ny3 = &y3*(1-&rate*0.5)+ ny2*(1-&rate); pyy3 = &y3*(1-&rate*0.5)*0.5+(&y3-&y3*(1-&rate*0.5))*0.25 + ny2*(1-&rate*0.5); ny4 = ny3*(1-&rate); pyy4 = ny3*(1-&rate*0.5); ny5 = ny4*(1-&rate); pyy5 = ny4*(1-&rate*0.5);
run; proc print data=want; run;
%mend test; %test (20,30,40, 0.06);
In the above program, ny1 is the number of persons and pyy1 is the number of person years contributed in the Year 1 . The logic for the first three years keeps changing. From the fourth year onward it remains the same formula. So, for 8th year the formula would be
ny8 = ny8*(1-&rate); pyy8 = ny8*(1-&rate*0.5)
I have shared the code for the first five years. But I need for extended periods of time like say 15 years. How can I best simplify my program. Also, I need the output in the below format (Add Cumulative Person years):
Year ny1 pyy1 Cumilative PY 1 19.4 9.85 9.85 2 47.336 33.593 43.443 3 83.2958 65.6159 109.0589 4 78.2981 80.797 189.8559 5 73.6002 75.9491 265.805
Thank you very much for all your help!!
I came across a lot of beginners begin as macro programmers than using SAS language. I wonder why that happens.
@Tomcaty Please follow the rules when you contemplating using macro language--? Below is some excerpt from my publishing at my college, maybe useful for you
1. Base SAS Programming Skills Example: Data step processing that includes PDV (program data vector), implicit loop that comprises Implicit Output. Implicit return etc:
2. Extensive knowledge of SAS functions and dataset options for Data manipulation A SAS function performs a computation or system manipulation on arguments and returns a value. In base SAS software, you can use SAS functions in DATA step programming statements, in macro language statements, and in Structured Query Language (SQL) Example using max, sqrt, min functions:
data _null_; x=max(cash,credit); x=sqrt(1500); NewCity=left(upcase(City)); x=min(YearTemperature-July,YearTemperature-Dec); s=repeat(’----+’,16); x=min((enroll-drop),(enroll-fail)); put x= s= ; run;
3. SAS Statements, keywords and Global Options :
4. Understanding data structures and mechanism of reading and writing external files.
5. Minimizing the number of programming lines marking less resource usage Example:
6. Proper use of formatted code for better readability helps in case of any future edits.
7. Choosing the right statement for conditional processing. For example, IF and Where Example:
8. Choosing either to program the code in a Datastep or Proc SQL by determining which is more efficient and serves best for a particular query. Example:
9. Knowledge in using different Proc’s effectively will help accomplishing faster execution of programs as opposed to Datastep execution.
10. Disk vs in memory processing
11. Familiarity of short cuts such as Arrays and iterative processing will result in speedy execution and minimize of the number of lines in writing a SAS program.
Importance of incorporating best practices using SAS Macro facility
First off, macro language is layer on top of sas language
Step1: Write an automated and debug a SAS program without macro coding
Step2: Generalize the program by replacing hardcoded values with macro variable references
Step3: Create a macro definition with macro parameters.
Step4: Add macro level programming for conditional and iterative processing.
Step5: Data driven customization. Data driven customization means flexibility of a macro execution using parameter validation that is data driven.
It is assumed SAS folks are highly proficient in the above 5 steps and considering that I would not go into the details of what’s a macro facility, a macro program or a SAS program flow and related concepts such as tokenization, compilation and execution.
For those who think they are slightly unfamiliar I would recommend comprehensive reading on parameterization- Positional keyword and mixed, macro storage, temporary and permanent catalog, creating macro variables in the Datastep and in SQL using macro functions and call and indirect references.
The common SAS Macro best practices I have encountered or experienced so far are as follows-
1. Choice of Positional vs. Keyword vs. Mixed Parameters
2. Choosing Local vs. Global Macro Variables
3. Suffixing a macro variable reference with a period (.).
4. Challenge of defining macros within a macro Nesting macro definitions inside other macros is usually unnecessary and inefficient. When you call a macro that contains a nested macro definition, the macro processor generates the nested macro definition as text and places it on the input stack. The word scanner then scans the definition and the macro processor compiles it. If you nest the definition of a macro that does not change, you cause the macro processor to compile the same macro each time that section of the outer macro is executed. Example: /* Nesting a Macro Definition--INEFFICIENT */ %macro stats1(product,year);
5. Conditional processing using % do loops and %if for conditional execution with focus on saving compile time.
I think what you are looking for is a DATA step, with no macro language. I will at least try to get the concept right ... not sure about all the formulas.
data want;
input y1 y2 y3 rate;
testnum=_n_;
cumulative_py=0;
ny = y1 * (1 - rate * 0.5);
pyy = ny * 0.5 + (y1 - ny) * 0.25;
year=1;
cumulative_py + pyy;
output;
pyy = y2 * (1 - rate * 0.5) * 0.5 + (y2 - y2*(1 - rate * 0.5)) * 0.25 + ny*(1 - rate*0.5);
ny = y2 * (1 - rate * 0.5) + ny*(1 - rate);
year=2;
cumulative_py + pyy;
output;
pyy = y3 * (1-rate*0.5) * 0.5 + (y3 - y3*(1 - rate * 0.5)) * 0.25 + ny * (1 - rate * 0.5);
ny = y3 * (1-rate*0.5) + ny*(1-rate);
year=3;
cumulative_py + pyy;
output;
do year=4 to 15;
pyy = ny*(1-rate*0.5);
ny = ny * (1-rate);
cumulative_py + pyy;
output;
end;
datalines;
20 30 40 0.06
;
This gives you the right results (I hope), but lets you add many more sets of tests by adding more lines of data in the same step.
It's untested, so might need some tweaking here and there.
Computation of PYY comes before calculation of NY, since PYY uses the old NY value (before applying updates for the current year).
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.