As @PaigeMiller remarked, you should provide example data as a data step, e.g.:
data have;
length PatientID $3 Contact_date Program_code activation_date Deactivation_date 8;
informat Contact_date activation_date Deactivation_date ddmmyy.;
format Contact_date activation_date Deactivation_date ddmmyy.;
input PatientID Contact_date Program_code activation_date Deactivation_date;
cards;
ID1 12/1/22 1 12/1/22 12/6/22
ID1 12/2/22 1 12/1/22 12/6/22
ID1 12/3/22 1 12/1/22 12/6/22
ID1 12/6/22 1 12/1/22 12/6/22
ID1 12/1/22 2 12/1/22 12/6/22
ID1 12/2/22 2 12/1/22 12/6/22
ID1 12/3/22 2 12/1/22 12/6/22
ID1 12/6/22 2 12/1/22 12/6/22
ID2 12/2/22 1 1/2/22 2/3/22
ID2 1/2/22 1 1/2/22 2/3/22
ID3 3/3/21 3 1/3/21 18/6/21
ID3 16/6/21 3 1/3/21 18/6/21
;run;
I would start by getting the counts for each patient and program_code. SQL can be used here:
proc sql;
create table counts as select
PatientID,Program_code,count(*) as count
from have
where Contact_date between activation_date and Deactivation_date
group by PatientID,Program_code;
quit;
Then you can use PROC SUMMARY to get the average number of contacts:
proc summary data=counts;
class PatientID;
var count;
output out=averages mean=avg_count;
run;
This will (as we did not use the NWAY option) create a table like this:
The first row (with missing PatientID and _TYPE_=0) is the grand total, the average for all patients. The _FREQ_ variable shows the number of input rows used to calculate the average. The next rows are for each patient. If you need the averages for the Program_code and not the PatientID, use that variable in the CLASS statement instead, and if you just need the grand total, drop the CLASS statement.
Of course, PROC SUMMARY could also have been used to create the first table as well. And PROC SQL can also calculate averages, but not on different levels at once (the _TYPE_).
... View more