**************************************************************************************************** * PROGRAM OVERVIEW **************************************************************************************************** * * PROGRAM: ms_pov1dose.sas * Created (mm/dd/yyyy): 06/01/2021 * *-------------------------------------------------------------------------------------------------- * PURPOSE: * This program will find all index dates that meet a cumulative and/or current filled daily * dose criteria * * Program inputs: * -Dataset with eligible index dates * -Dataset with all claims * * Program outputs: * -Dataset with eligible index dates meeting the dose criteria * -Dataset with index dates not meeting the dose criteria * * PARAMETERS: * -InFile = Name of the dataset with eligible index dates * -ClaimFile = Name of the dataset with all claims * -ExclIndexFile = Name of the dataset with index dates excluded due to not meeting criteria * -OutFile = Name of the output dataset meeting the dose criteria * -mincumdose = Minimum prior cumulative dose * -maxcumdose = Maximum prior cumulative dose * -mincfdd = Minimum current filled daily dose * -maxcfdd = Maximum current filled daily dose * -lookback = Number of days prior to index date to evaluate mincumdose/maxcumdose * -RxSupVar = Variable holding dispensing RX Days Supply * * Programming Notes: * - Cumulative dose is evaluated in the window [-lookback, indexdate -1] * *-------------------------------------------------------------------------------------------------- * CONTACT INFO: * Sentinel Coordinating Center * info@sentinelsystem.org * *-------------------------------------------------------------------------------------------------- ***************************************************************************************************; %macro ms_pov1dose(InFile=, ClaimFile=, ExclIndexFile=, OutFile=, Mincumdose=, Maxcumdose=, Mincfdd=, Maxcfdd=, Lookback=, RxSupVar=); %put =====> MACRO CALLED: ms_pov1dose; /*---------------------------------------------------------------------------------------------------------- Cumulative Dose ----------------------------------------------------------------------------------------------------------*/ %if &mincumdose. ne . | &maxcumdose. ne . %then %do; /*---------------------------------------------------------------------------------------------------- Select claims in lookback window - cumulative dose ----------------------------------------------------------------------------------------------------*/ proc sql noprint; create table _claimsinlookback as select in.patid, in.adate, claim.adate as claimadate, claim.expiredt as claimexpiredt, claim.cumdose, claim.&rxsupvar. from &infile. as in, &claimfile. as claim where in.patid = claim.patid and %MS_PeriodsOverlap(period1=in.Adate-&lookback. in.Adate-1, period2=claim.adate claim.ExpireDt); quit; /*---------------------------------------------------------------------------------------------------- Remove dose occuring outside the looback window ----------------------------------------------------------------------------------------------------*/ data _claimsinlookback1; set _claimsinlookback; ToDeductBf=0; ToDeductAf=0; if claimadate < adate-&lookback. then do; *Starts before lookback period; ToDeductBf=adate-&lookback.-claimadate; end; if claimexpiredt > adate-1 then do; *Ends after lookback period; ToDeductAf=claimexpiredt-adate-1; end; if cumdose > 0 then cumdose=cumdose *(&rxsupvar.-sum(ToDeductBf,ToDeductAf))/&rxsupvar.; drop ToDeductBf ToDeductAf &rxsupvar. claimadate claimexpiredt; run; /*---------------------------------------------------------------------------------------------------- Compute total cumulative dose in lookback window and output all index dates meeting/not meeting criteria ----------------------------------------------------------------------------------------------------*/ proc means data=_claimsinlookback1 noprint nway; var cumdose; class patid adate; output out=_claimsdose sum=; run; data _claimsmeetingdose(drop=attrition_reason) _doseattrition1(keep=patid adate attrition_reason); merge _claimsdose(in=a) &infile.(in=b keep=patid adate); by patid adate; length attrition_reason 3; attrition_reason = 1; /*cumulative dose*/ if a and b then do; %if &mincumdose. ne . AND &maxcumdose. ne . %then %do; if round(cumdose,1)>=&mincumdose. AND round(cumdose,1)<=&maxcumdose. then output _claimsmeetingdose; else output _doseattrition1; %end; %else %if &mincumdose. ne . %then %do; if round(cumdose,1)>=&mincumdose. then output _claimsmeetingdose; if round(cumdose,1)<&mincumdose. then output _doseattrition1; %end; %else %if &maxcumdose. ne . %then %do; if round(cumdose,1)<=&maxcumdose. then output _claimsmeetingdose; if round(cumdose,1)>&maxcumdose. then output _doseattrition1; %end; end; else if b and not a then do; %if &mincumdose. ne . AND &maxcumdose. ne . %then %do; /*dosen't meet mincumdose*/ output _doseattrition1; %end; %else %if &mincumdose. ne . %then %do; output _doseattrition1; %end; %else %if &maxcumdose. ne . %then %do; /*index claim always meets maxcumdose*/ %end; end; run; proc sort data=_claimsmeetingdose nodupkey; by _ALL_; run; proc sort data=_doseattrition1 nodupkey; by _ALL_; run; %if &mincumdose. = . %then %do; data &outfile.; if 0 then set _doseattrition1(keep=patid adate); declare hash m(dataset:"_doseattrition1"); m.definekey('patid', 'adate'); m.definedone(); do until (eof); set &infile. end=eof; if m.find() ne 0 then output &outfile.; end; run; %end; %else %do; data &outfile.; if 0 then set _claimsmeetingdose(keep=patid adate); declare hash m(dataset:'_claimsmeetingdose'); m.definekey('patid', 'adate'); m.definedone(); do until (eof); set &infile. end=eof; if m.find() = 0 then output &outfile.; end; run; %end; proc datasets library=work nolist nowarn; delete _claimsinlookback _claimsinlookback1 _claimsmeetingdose; quit; %end; /*cumulative dose*/ /*---------------------------------------------------------------------------------------------------------- Current Filled Daily Dose ----------------------------------------------------------------------------------------------------------*/ %if &mincfdd. ne . | &maxcfdd. ne . %then %do; /*---------------------------------------------------------------------------------------------------- Determine # of stockgroups - if >1 recompute cFDD on index date ----------------------------------------------------------------------------------------------------*/ proc sql noprint; select distinct stockgroup into :defstocklist separated by ' ' from infolder.&cohortcodes.(where=(indexcriteria='DEF' and group = "&itgroup.")); quit; %if %eval(%sysfunc(countw(%str(&defstocklist.), ' '))>1) %then %do; %let sameday_supp_oper=sum; %let sameday_amt_oper=sum; %if &unique_stock_params >=1 %then %do; data _null_; set STOCKPILE_NONCOVAR; where group="&ITGROUP" and stockgroup = "%scan(%str(&defstocklist.), 1)"; /*need to determine whether to max rxsup*/ if lowcase(strip(substr(SameDay,1,1))) = 'x' then call symputx("sameday_supp_oper",'max'); run; %end; /*Aggregate same day claims - modified from ms_stockpiling*/ proc sql noprint; create table _claimsinlookback as select d.patid, d.adate, (c.strength*c.&rxamtvar.)/c.&rxsupvar. as cfdd from (select b.* ,a.strength from (select patid ,adate ,sum(strengthamt)/sum(&rxamtvar.) as strength from (select patid ,(strength * &rxamtvar.) as strengthamt ,&rxamtvar. ,adate from &claimfile.) group by patid, adate) as a inner join (select patid ,adate ,&sameday_supp_oper.(&rxsupvar.) as &rxsupvar. ,&sameday_amt_oper.(&rxamtvar.) as &rxamtvar. from &claimfile. group by patid, adate) as b on a.adate = b.adate and a.patid = b.patid) as c inner join &infile. as d on c.patid = d.patid and c.adate = d.adate; quit; %end; %else %do; proc sql noprint; create table _claimsinlookback as select in.patid, in.adate, (claim.strength*claim.&rxamtvar.)/claim.&rxsupvar. as cfdd from &infile. as in, &claimfile. as claim where in.patid = claim.patid and in.adate = claim.adate; quit; %end; data _claimsmeetingdose(drop=attrition_reason) _doseattrition2(keep=patid adate attrition_reason); set _claimsinlookback; length attrition_reason 3; %if &mincfdd. ne . AND &maxcfdd. ne . %then %do; if round(cfdd,1)>=&mincfdd. AND round(cfdd,1)<=&maxcfdd. then do; output _claimsmeetingdose; end; else do; if round(cfdd,1)<&mincfdd. then attrition_reason = 2; /*does not meet mincfdd*/ else if round(cfdd,1)>&maxcfdd. then attrition_reason = 3; /*does not meet maxcfdd*/ output _doseattrition2; end; %end; %else %if &mincfdd. ne . %then %do; attrition_reason = 2; if round(cfdd,1)>=&mincfdd. then output _claimsmeetingdose; else output _doseattrition2; %end; %else %if &maxcfdd. ne . %then %do; attrition_reason = 3; if round(cfdd,1)<=&maxcfdd. then output _claimsmeetingdose; else output _doseattrition2; %end; run; proc sort data=_claimsmeetingdose nodupkey; by _ALL_; run; proc sort data=_doseattrition2 nodupkey; by _ALL_; run; data &outfile.; if 0 then set _claimsmeetingdose(keep=patid adate); declare hash m(dataset:'_claimsmeetingdose'); m.definekey('patid', 'adate'); m.definedone(); do until (eof); set &infile. end=eof; if m.find() = 0 then output &outfile.; end; run; proc datasets library=work nolist nowarn; delete _claimsinlookback _claimsmeetingdose; quit; %end; /*current filled daily dose*/ /*---------------------------------------------------------------------------------------------------------- Create final dataset containing excluded index dates ----------------------------------------------------------------------------------------------------------*/ data &ExclIndexFile.; set _doseattrition:; run; proc datasets library=work nolist nowarn; delete _doseattrition:; quit; %put NOTE: ********END OF MACRO: ms_pov1dose ********; %mend ms_pov1dose;