/*------------------------------------------------ EPISODE GENERATION CODE FROM RAW MDS 2.0 DATA Release date: February 14, 2012 Copyright ©2012 Zachary Gassoumis, Kathryn Thomas, Kathleen Wilber Below is a macro written for the systematic generation of episodes of care from MDS data. It makes several assumptions about the format of your data, including: - all variable names are as given in the MDS, ordered in the dataset in the same order in which they appear on the MDS - dates are coded as text, in the format yyyymmdd, with missing coded as asterisks (i.e., ********) The macro can be invoked by running the code in this file, then running the %episodes macro in a file of your choosing. There are six parameters in the macro, as follows: 1) mainlib - the location of your primary library, surrounded by quotes. 2) master - the location of the library that contains your master data, surrounded by quotes (note: could be the same location as mainlib). 3) masterfile - the filename of your master data file (note: for multiple files, simply precede the second and subsequent filenames with "master." - e.g., "file1 master.file2"). 4) date1 - the date at which you wish to begin your sample selection (note: due to left censoring, the first episode will begin 30 days after date1). 5) date2 - the date at which you wish to end your sample selection. 6) rcensor - the number of days you wish to allocate as the right censor criterion. Note: date1 and date2 must be entered in format ddmmmyyyy. E.g., July 9, 2010 would be entered 09jul2010. EXAMPLE: I want to generate episodes for all data from Jan 1, 2001 to Dec 31, 2003, with a right censor of 180 days. The master dataset is in the file C:\master\maindata.sas7bdat, and your working library is C:\library\. The macro you should run is: %episodes("C:\library","C:\master",maindata,01jan2001,31dec2003,180) The resultant dataset, mds_episodes in your mainlib folder, will have episodes with start dates between Feb 1, 2001 (due to the 30-day left censor) & Jul 3, 2003 (due to the 180-day right censor). There are a few primary new variables of interest: - epi_beg: episode start date - epi_end: episode end date - epi_length: episode length - shortbounce: total number of "bounces" during the episode (i.e., how many times the resident left & re-entered the nursing facility during the course of one episode) - r3a1 through r3a9: number of "bounces" to each r3a location during the episode If you use this code in generating episodes, please make reference to it using the following citation: Thomas, K. E., Gassoumis, Z. D., & Wilber, K. H. (2010). Conversion diversion: Participation in a social HMO reduces the likelihood of converting from short-stay to long-stay nursing facility placement. Journal of the American Medical Directors Association, 11(5), 333-337. Please report any errors to the authors via e-mail: Zach Gassoumis - gassoumi@usc.edu Kate Wilber - wilber@usc.edu ------------------------------------------------*/ %macro episodes(mainlib,master,masterfile,date1,date2,rcensor); libname mainlib &mainlib; libname master &master; data _null_; call symput('ycu',year("&date2"d)-99); day=day("&date1"d);call symput('d1t',day*1000000+month("&date1"d)*10000+year("&date1"d)); if day le 9 then call symput('d1t',0||left(symget('d1t'))); call symput('d1',trim(left(symget('d1t')))); call symput('date3',"&date2"d+1); run; options yearcutoff=&ycu; %macro bdest(); if bdest = "-" then do; gapdash = (gapdash*r3adash + gap) / (r3adash + 1); r3adash = r3adash + 1; end; %do i=1 %to 9; if bdest = "&i" then do; gap&i = (gap&i*r3a&i + gap) / (r3a&i + 1); r3a&i = r3a&i + 1; end; %end; %mend bdest; %macro breset(); bdest = ""; shortbounce = 0; r3adash = 0; r3a1 = 0; r3a2 = 0; r3a3 = 0; r3a4 = 0; r3a5 = 0; r3a5_90 = 0; r3a6 = 0; r3a7 = 0; r3a8 = 0; r3a9 = 0; gapdash = 0; gap1 = 0; gap2 = 0; gap3 = 0; gap4 = 0; gap5 = 0; gap6 = 0; gap7 = 0; gap8 = 0; gap9 = 0; %mend breset; data mds1; set master.&masterfile; format entryd mmddyy10. exitd mmddyy10. doi mmddyy10. datesort 1. entryyr 4. exityr 4. entrymo 2. exitmo 2. entrydt 2. exitdt 2.; if aa8a in ("01","06","07","08","09"); if aa8a = "01" AND ab1 < "&d1" AND a4a = "********" then delete; if aa8a = "01" and a4a ne "********" then entry_doi = a4a; else if aa8a = "01" and a4a = "********" then entry_doi = ab1; else if aa8a = "08" then entry_doi = ab1; else if aa8a = "09" then entry_doi = a4a; else entry_doi = ""; if entry_doi = "********" then entry_doi = ""; if aa8a = "06" then exit_doi = r4; else if aa8a = "07" then exit_doi = r4; else if aa8a = "08" then exit_doi = r4; else exit_doi = ""; if exit_doi = "********" then exit_doi = ""; entryyr = input(substr(entry_doi,1,4),4.); entrymo = input(substr(entry_doi,5,2),2.); entrydt = input(substr(entry_doi,7,2),2.); entryd = mdy(entrymo,entrydt,entryyr); exityr = input(substr(exit_doi,1,4),4.); exitmo = input(substr(exit_doi,5,2),2.); exitdt = input(substr(exit_doi,7,2),2.); exitd = mdy(exitmo,exitdt,exityr); if aa8a = "08" then do; btwdate = exitd - entryd; if btwdate gt 14 then entryd = exitd - 14; end; if exitd then doi = exitd; else doi = entryd; if aa8a in ("06","07") then datesort = 1; else if aa8a = "08" then datesort = 2; else if aa8a = "01" then datesort = 3; else if aa8a = "09" then datesort = 4; proc sort data=mds1 out=mds1sort; by mdsstid doi datesort; where "&date1"d le doi le "&date2"d; run; data mds2 (keep = mdsstid epi_beg epi_end shortbounce gap bdest r3adash--gap9 first_date r3a5_90); set mds1sort; by mdsstid doi datesort; format epi_beg mmddyy10. epi_end mmddyy10. shortbdate mmddyy10. r3adash 2.r3a1 2. r3a2 2. r3a3 2. r3a4 2. r3a5 2. r3a6 2. r3a7 2. r3a8 2. r3a9 2. gapdash 8.4 gap1 8.4 gap2 8.4 gap3 8.4 gap4 8.4 gap5 8.4 gap6 8.4 gap7 8.4 gap8 8.4 gap9 8.4 first_date mmddyy10. r3a5_90 2.; retain epi_beg epi_end shortbounce shortbdate gap bdest r3adash--gap9 first_date r3a5_90; if first.mdsstid then do; epi_beg = .; epi_end = .; shortbdate = .; first_date = .; %breset; end; * Scenario 1a; if epi_beg = . AND datesort = 3 AND entryd lt ("&date2"d - &rcensor) then do; if entryd gt ("&date1"d + 30) AND (first_date = . OR entryd gt (first_date + 30)) then do; epi_beg = entryd; shortbdate = entryd; end; else if entryd lt ("&date1"d + 30) then first_date = doi; end; * Scenario 1b; if epi_beg = . AND datesort ne 3 then first_date = doi; * Scenario 2; if epi_beg AND (shortbdate gt epi_end OR epi_end = .) AND datesort = 1 then do; epi_end = exitd; bdest = r3a; end; * Scenario 3; if epi_beg AND epi_end AND exitd gt epi_end AND datesort = 2 then do; gap = max(entryd - epi_end,0); if shortbdate le epi_end AND gap le 30 then do; if epi_end - epi_beg le 90 and bdest = "5" then r3a5_90 = r3a5_90 + 1; epi_end = max(epi_end,exitd); shortbounce = shortbounce + 1; %bdest; bdest = r3a; end; if shortbdate le epi_end AND gap gt 30 then do; output; epi_beg = .; epi_end = .; %breset; end; end; * Scenario 4; if epi_beg AND epi_end = . AND datesort = 2 then do; epi_end = exitd; bdest = r3a; end; * Scenario 5; if epi_beg AND epi_end AND datesort = 4 then do; gap = entryd - epi_end; if shortbdate le epi_end AND gap le 30 then do; if epi_end - epi_beg le 90 and bdest = "5" then r3a5_90 = r3a5_90 + 1; if entryd ne shortbdate then shortbounce = shortbounce + 1; %bdest; end; if shortbdate le epi_end AND gap gt 30 then do; output; epi_beg = .; epi_end = .; %breset; end; shortbdate = entryd; end; * Scenario 6; if epi_beg AND epi_end AND datesort = 3 then do; gap = entryd - epi_end; if shortbdate le epi_end AND gap le 30 then do; if epi_end - epi_beg le 90 and bdest = "5" then r3a5_90 = r3a5_90 + 1; if entryd ne shortbdate then shortbounce = shortbounce + 1; %bdest; end; if shortbdate le epi_end AND gap gt 30 then do; output; epi_end = .; %breset; if entryd lt ("&date2"d - &rcensor) then epi_beg = entryd; else epi_beg = .; end; shortbdate = entryd; end; * Scenario 7; if epi_beg AND last.mdsstid AND datesort in (3,4) then do; epi_end = &date3; output; end; * Scenario 8; if epi_end AND last.mdsstid AND datesort in (1,2) then output; run; *merging with admission data; data mds2b; set mds2; format entryd mmddyy10. exitd mmddyy10.; entryd = epi_beg; exitd = epi_end; epi_length = epi_end - epi_beg; run; proc sort data=sashelp.vcolumn out=mdsmeta; by libname memname; data _null_; set mdsmeta; by libname memname; where libname = "WORK" and memname = "MDS1"; if last.memname then call symput("mdsmetalast",name); run; data mds1b; set mds1 (drop = r3a -- &mdsmetalast); where aa8a = "01"; run; proc sort data=mds1b; by mdsstid entryd r2b; proc sort data=mds2b; by mdsstid entryd; run; data mds3; merge mds2b mds1b; by mdsstid entryd; if epi_end; run; proc sort data=mds3; by mdsstid epi_beg r2b; data mds3b; set mds3; by mdsstid epi_beg; if first.epi_beg; run; *merging with discharge data; data mds1c (drop = aa8a); set mds1 (keep = mdsstid aa8a exitd r4 r3a); where aa8a IN ("06","07","08"); aa8adischarge = aa8a; run; proc sort data=mds1c; by mdsstid exitd; proc sort data=mds3b; by mdsstid exitd; run; data mainlib.mds_episodes; merge mds3b mds1c; by mdsstid exitd; if epi_beg; run; %mend episodes;