/** @file ms_envelope.sas @brief This macro uses data from the SDD to recode non-inpatient encounters to inpatient if they were determined to have occurred during an inpatient stay. @details - Extract IP encounters (occuring after &mindate. when specified) - Remove encounter ids to delete if required - Collapse IP encounters into IP episodes to reduce number of observations involved in joining datasets. - For each record in INFILE within an inpatient stay, recode encounter type as inpatient if not already coded as such. @par Program inputs - &ENCOUNTERINFILE. (Dataset with encounter data.) - &INFILE. (Dataset with diagnosis/procedure claims data.) @par Program outputs - &OUTFILE. (Dataset with reclassified claims.) * **Usage** %ms_envelope(INFILE=worktemp.meds, ENCOUNTERINFILE=indata.&ENCTABLE., MINDATE=&studystartdate, OUTFILE=worktemp.meds); @param [in] INFILE Name of SAS dataset with diagnosis and/or procedure claims data. @param [in] ENCOUNTERINFILE Name of SAS dataset with encounter data. @param [in] MINDATE Extract all claims occuring on or after this date. @param [out] OUTFILE Name of output file with reclassified claims. <h4> SAS Macros Dependencies </h4> @li ms_delencounterids.sas @note This operation is done without using the ENCOUNTERID variable, as this variable can be inconsistent across data partner datasets. @author Sentinel Coordinating Center (info@sentinelsystem.org) **/ %macro MS_ENVELOPE(INFILE=,ENCOUNTERINFILE=,MINDATE=,OUTFILE=); %put =====> MACRO CALLED: ms_envelope; *Reclassification as inpatient all selected claims within admission and discharge dates of an inpatient stay; *Get Unique ADate-Ddate combinations; proc sort nodupkey data=&ENCOUNTERINFILE.(keep=PatId Adate Ddate EncType %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; encounterid %end; where=(EncType='IP' %if %str("&mindate") ne %str("") %then %do; and max(Adate, Ddate) >= &mindate. %end;)) out=_IPdates(keep=PatId Adate Ddate %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; encounterid %end;); by PatId Adate Ddate; run; *Delete data for encounterids in DPs &ENCIDTOEXCLUDE. files; %ms_delencounterids(datafile=_IPdates, EncIdsfile=&ENCIDTOEXCLUDE., Outfile=_IPdates); %if &run_envelope. = 0 %then %do; %let sign = %str(<=); * Many consecutive single day encounters can be present for a patient in _IPDates. For efficiency purposes, collapse IP encounters into IP episodes considering a 0 day gap to reduce the number of observations before joining with &INFILE.; data _IPdates; set _IPdates %if %str(&ENCIDTOEXCLUDE.) ne %str() %then %do; (drop=encounterid) %end;; by PatId Adate; length IP_episode 3; if Adate - max(lag(Adate),lag(Ddate))-1 > 0 then IP_episode=IP_episode+1; if first.Patid then IP_episode=1; if missing(Ddate) then Ddate=Adate; retain IP_episode; run; proc sql noprint undo_policy=none; create table _IPdates as select PatId, min(adate) as IP_Adate format=mmddyy10. length=4, max(ddate) as IP_Ddate format=mmddyy10. length=4 from _IPdates group by Patid, IP_episode; quit; %end; %else %do; %let sign = %str(<); proc datasets nowarn nolist lib=work; modify _IPdates; rename adate = IP_Adate; rename ddate = IP_Ddate; quit; %end; *For each record in &INFILE within an inpatient stay, recode encounter type as inpatient if not already coded as such; data &OUTFILE.; if 0 then set _IPdates(keep=PatId IP_Adate IP_DDate); declare hash h(dataset:"_IPdates",HASHEXP:16, multidata:"Y"); h.definekey('PatId'); h.definedata('IP_Adate', 'IP_DDate'); h.definedone(); do until (eof); set &INFILE. end=eof; drop IP_:; if h.num_items>0 then do; rc = h.find(); do while (rc = 0); if EncType ne 'IP' and IP_ADate &sign. ADate <= max(IP_ADate,IP_DDate) then do; pdx='X'; EncType='IP'; end; rc = h.find_next(); end; drop rc; end; output; end; run; proc datasets library = work nolist nowarn nodetails; delete _IPDates; quit; %put NOTE: ******** END OF MACRO: ms_envelope ********; %mend MS_ENVELOPE;