The input dataset 'fills' is entirely generated procedurally in the first DATA step. It does not depend on any external data source. It serves only as an example for the PDC calculation algorithm.
1 Code Block
DATA STEP Data
Explanation : This block creates a test dataset named 'fills'. It simulates prescription data for 100 patients by generating an identifier (patientICN), a dispensing date (edate), a treatment duration (days), and an optional death date (dod) for censoring. Values are randomly generated to create a realistic dataset for demonstration.
Copied!
data fills;
length patientICN 5 dod edate days 5;
format edate date9.;
array T {5} _temporary_ (30, 30, 30, 90, 10);
do i=1 to 100;
patientICN=1000+i;
edate='01Jan2020'd + int(ranuni(0)*100);
slack=int(rand('erlang', 2)*10);
dod=.;
if ranuni(0)<0.15 then dod=edate+int(ranuni(0)*730);
do while (1);
days=T[int(ranuni(0)*dim(T)+1)];
output;
edate+max(1,int(days+rand('normal')*5))+slack;
if ranuni(0)<.05 then leave;
end;
end;
drop i;
run;
1
DATA fills;
2
LENGTH patientICN 5 dod edate days 5;
3
FORMAT edate date9.;
4
array T {5} _temporary_ (30, 30, 30, 90, 10);
5
DO i=1 to 100;
6
patientICN=1000+i;
7
edate='01Jan2020'd + int(ranuni(0)*100);
8
slack=int(rand('erlang', 2)*10);
9
dod=.;
10
IF ranuni(0)<0.15THEN dod=edate+int(ranuni(0)*730);
11
DO while (1);
12
days=T[int(ranuni(0)*dim(T)+1)];
13
OUTPUT;
14
edate+max(1,int(days+rand('normal')*5))+slack;
15
IF ranuni(0)<.05THEN leave;
16
END;
17
END;
18
drop i;
19
RUN;
2 Code Block
PROC PRINT
Explanation : Displays the first 30 observations of the 'fills' dataset that has just been created. This allows for a quick visual check to ensure that the test data has been generated correctly.
Copied!
title 'first 50 obs of fake input data';
proc print data=fills (obs=30); run;
1
title 'first 50 obs of fake input
2
data';
3
PROC PRINT
4
DATA=fills (obs=30);
5
6
RUN;
7
3 Code Block
PROC SORT
Explanation : Sorts the 'fills' dataset by patient ID (patientICN) and then by dispensing date (edate). This step is crucial for the sequential processing by patient performed in the next calculation block.
Copied!
proc sort data=fills; by patientICN edate; run;
1
PROC SORTDATA=fills; BY patientICN edate; RUN;
4 Code Block
DATA STEP Data
Explanation : This block is the core of the algorithm. It reads the sorted data and, for each patient, calculates the medication coverage days. Using `first.patientICN` and `last.patientICN` instructions, it initializes and finalizes calculations for each individual. It iterates through prescriptions, 'stacks' coverage days, and increments the counter for the correct time interval. At the end of a patient's data, it calculates the PDC for each interval and generates a single output row for that patient in the 'pdc_ptlev' table.
Copied!
%let interv=90; * number of days in interval ;
%let ninterv=12; * number of intervals ;
data pdc_ptlev;
set fills;
by patientICN edate;
length currend 5 currpos 3 bndry 3 pdc_p1-pdc_p&ninterv 5;
retain currend currpos pdc_:;
array p {*} pdc_:;
array ends {&ninterv} _temporary_;
array D {&ninterv} _temporary_;
if first.patientICN then do;
currend=.;
currpos=1;
bndry=0;
do i=1 to dim(p);
p[i]=0;
bndry+&interv;
ends[i]=edate+bndry;
D[i]=min(&interv,max(0/(DOD>.),&interv-(ends[i]-DOD)));
end;
end;
currend=max(currend, edate);
do while (days>0);
currend+1;
days=days-1;
if currend>ends[dim(ends)] or .<dod<=currend then leave;
do while (ends[currpos]<=currend and currpos<dim(ends));
currpos+1;
end;
p[currpos]+1;
end;
if last.patientICN then do;
do i=1 to dim(p);
p[i]=p[i]/D[i];
end;
output;
end;
keep patientICN pdc_:;
format pdc_: percent8.1;
run;
Explanation : Displays the first 30 observations of the final 'pdc_ptlev' dataset. Each row represents a patient, and the columns show the PDC for each interval. The `heading=v` option allows for vertical display of headers for better readability.
Copied!
title 'first 30 obs of output -- one row/patient';
proc print data=pdc_ptlev (obs=30) heading=v width=min; run;
title;
1
title 'first 30 obs of output -- one row/patient';
2
PROC PRINT
3
DATA=pdc_ptlev (obs=30) heading=v width=min;
4
5
RUN;
6
title;
7
This material is provided "as is" by We Are Cas. There are no warranties, expressed or implied, as to merchantability or fitness for a particular purpose regarding the materials or code contained herein. We Are Cas is not responsible for errors in this material as it now exists or will exist, nor does We Are Cas provide technical support for it.
SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration. WeAreCAS is an independent community site and is not affiliated with SAS Institute Inc.
This site uses technical and analytical cookies to improve your experience.
Read more.