%macro fine_stratification (in_data= , exposure= , PS_provided= no , ps_var= , ps_class_var_list= , ps_cont_var_list= , PSS_method=exposure, n_of_strata= , out_data= PS_FS, id_var= , effect_estimate= , outcome= , survival_time= , out_excel= , ps_dist_plots= no, ps_dist_figure= ); ************************************************************************************************************* ** step 0- Create the crude Table 1 **; *************************************************************************************************************; %table1 (in_for_table1= &in_data, treatment_var= &exposure, categorical_var_list= &ps_class_var_list, continuous_var_list= &ps_cont_var_list, out_table1= Crude_T1); ************************************************************************************************************* ** step 1- build and calculate the PS- if not already done **; *************************************************************************************************************; title 'PS model'; %let ps_provided1 = %upcase(&PS_provided); %if "&PS_provided1" = "NO" %then %do; ods output Association=save_c; proc logistic data=&in_data desc ; class &ps_class_var_list; model &exposure= &ps_cont_var_list &ps_class_var_list; output out=sample_ps p=&ps_var; run; ods output clear; data save_c; set save_c; where label2='c'; keep label2 nvalue2; run; %end; %let ps_provided1 = %upcase(&PS_provided); %if "&PS_provided1" = "YES" %then %do; data sample_ps; set &in_Data; run; %end; title; ************************************************************************************************************* ** step 2- trim the non-overlapping regions of the PS **; *************************************************************************************************************; *figure out the region of overlap; proc sql noprint; create table bounds_pscore as select max(&ps_var) as max_p, min(&ps_var) as min_p, &exposure from sample_ps group by &exposure; quit; *Save upper and lower bound of overlapping PS regions; proc sql noprint; select max(min_p) into: overlap_lower_bound from bounds_pscore; quit; proc sql noprint; select min(max_p) into: overlap_upper_bound from bounds_pscore; quit; *delete non-overlapping observations; data sample_ps_trimmed; set sample_ps; where &overlap_lower_bound<=&ps_var<=&overlap_upper_bound; run; ************************************************************************************************************* ** step 3- Conduct propensity score stratification *************************************************************************************************************; %let PSS_method1 = %upcase(&PSS_method); %if "&PSS_method1" = "EXPOSURE" %then %do; ** separate exposed only **; data only_exp; set sample_ps_trimmed; where &exposure=1; run; ** Create strata based on the PS distribution of the exposed **; proc rank data=only_exp groups=&n_of_strata out=fs_exp; ranks strata_sas; var &ps_var; run; data fs_exp; set fs_exp; strata=1+strata_sas; * number of strata indicator, since proc rank assigns strata beginning from 0, we add 1 here **; drop strata_sas; run; *Get bounds of the PS for strata created; proc means data=fs_exp noprint; class strata; var &ps_var; output out=bounds_for_fs n=n min(&ps_var)=PS_min max(&ps_var)=PS_max; run; data bounds_for_fs; set bounds_for_fs; where strata ne .; *delete overall mean; run; ** Now, using the bounds of PS from the exposed distribution, assign strata in the unexposed patients; %let n=&n_of_strata; %macro strata_in_unexp; ** lets save the bounds for each separate strata into SAS datasets, which will be merged to the unexposed only cohort for the ease of strata creation in the next step **; %do strata= 1 %to &n; proc sql ; create table PSvalue&strata as select (ps_min) as ps_low&strata from bounds_for_fs where strata=&strata; quit; %end; data only_unexp; set sample_ps_trimmed; where &exposure=0; run; data only_unexp1; merge only_unexp psvalue1-psvalue&n; run; ** the above merge creates a dataset with extra columns with each column containing value of the lower bound of the stratum boundary calculated from the ps distribution of the exposed (eg 5 strata= 5 extra columns). This information is used below to determine stratum membership of each unexposed subject. however, before moving on, we fill all the rows with the values of this variable by using missing=mean because the merge only fills one row since the datasets psvalue1 through n only has one row; proc stdize out=only_unexp2 reponly missing=mean; run; ** create strata **; data unexp_strata; set only_unexp2; array abc(*) ps_low: ; do i=3 to dim(abc) while (strata=.); if 0<=&ps_varinput-catalog specifies the input catalog that stores the graphics output that you want to use with the GREPLAY procedure. If you omit the libref, SAS/GRAPH looks for the catalog in the temporary WORK library.; tdef graf2by1 1 / ulx = 0 uly = 100 urx = 100 ury = 100 llx = 0 lly = 50 lrx = 100 lry = 50 2 / ulx = 0 uly = 47 urx = 100 ury = 47 llx = 0 lly = 0 lrx = 100 lry = 0; template graf2by1; ** tell sas to use the template you just created; treplay 1:FIGURE1 2:FIGURE2; *Replays graphics entries into template panels. TREPLAY copies one or more entries from the graphics input catalog into a template-entry in the graphics output catalog, using positioning information provided by the template.; run; ods pdf close; ods listing; proc greplay igout = work.gseg nofs; delete _all_; run; quit; %end; title; %mend;