-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAim 2 Non-binary experiment 04.02.2019.sas
More file actions
340 lines (286 loc) · 10.9 KB
/
Aim 2 Non-binary experiment 04.02.2019.sas
File metadata and controls
340 lines (286 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/*********************************************************************************
*
* Study of Environment Lifestyle & Fibroids (SELF)
* Hoffman Dissertation -- Aim 2 Non-binary IPW Experiment
* 03/13/2019
*
*********************************************************************************/
title ' '; title2 ' '; title3 ' '; title4 " "; title5 " "; title6 " ";
/*********************************************************************************
* Non-binary Exposure IPW (Changed 3rd row confounder to 0)
*********************************************************************************/
data IPW_1;
input ID Exposure Outcome Confounder;
CARDS;
1 0 1 0
3 0 0 0
2 0 1 0
4 0 1 1
17 0 1 1
5 1 1 0
18 1 0 0
7 1 0 1
8 1 0 1
6 1 1 1
10 2 1 0
11 2 1 0
12 2 0 0
19 2 1 0
9 2 0 1
20 3 1 0
13 3 1 1
14 3 1 1
15 3 0 1
16 3 1 1
;
run;
ods rtf style=htmlblue;
proc freq data=IPW_1; tables Exposure Outcome Confounder; run;
/*Step 1: Crude Model*/
title3 "Crude (Unadjusted) Model";
proc genmod data=IPW_1 desc;
class Exposure (order = internal ref=first);
model Outcome=Exposure/link=log dist=binomial;
estimate "Risk of outcome by exposure 1 v 0" Exposure 1 0 0 -1;
estimate "Risk of outcome by exposure 2 v 0" Exposure 0 1 0 -1;
estimate "Risk of outcome by exposure 3 v 0" Exposure 0 0 1 -1;
run;
/*Step 2: PS Model*/
title3 "Propensity Score Model";
proc logistic data=IPW_1 descending;
class Exposure (order = internal ref=last) Confounder;
model Exposure = Confounder /link=glogit;
output out=ps_data_1 predicted=ps;
run;
/*Step 3: PS Curves*/
data ps_data_2;
set ps_data_1;
if Exposure = 0 then ps_0 = ps;
else ps_0 = .;
if Exposure = 1 then ps_1 = ps;
else ps_1 = .;
if Exposure = 2 then ps_2 = ps;
else ps_2 = .;
if Exposure = 3 then ps_3 = ps;
else ps_3 = .;
run;
proc freq data=ps_data_2; tables ps_0 ps_1; run;
%macro level (trt = );
proc kde data=ps_data_2;
univar ps_0 ps_1 ps_2 ps_3 / plots=densityoverlay;
title4 "Propensity score distributions by treatment group";
title5 "Multinomial Logistic Model PS";
title6 "Probability of being in treatment group &trt";
where _level_ = &trt;
run;
%mend;
%level (trt = 0);
%level (trt = 1);
%level (trt = 2);
%level (trt = 3);
title4 " "; title5 " "; title6 " ";
/*Step 4: IPW*/
/*Estimation of numerator of stabalized ip weights*/
title3 "Empty Model For Stabilized Weight Numerators";
proc logistic data=IPW_1 descending;
ods exclude ClassLevelInfo Type3 Association FitStatistics GlobalTests Oddsratios;
class Exposure (order = internal ref=first);
model Exposure = /link=glogit;
output out=ps_data_1_n (keep= id _level_ pn_Exposure) p=pn_Exposure;
run;
/*Transposing the data so that numerators and denominators for weights are in one place*/
data ps_data_1x; set ps_data_1; keep id Exposure _level_ ps; run;
data for_set; set IPW_1; run;
proc sort data=ps_data_1x; by id; run;
proc transpose data=ps_data_1x out = ps_data_1y prefix = ps_; var ps; id _level_; by id; run;
proc sort data=ps_data_1_n; by id; run;
proc transpose data=ps_data_1_n out = ps_data_1n_y prefix = mp_; var pn_Exposure; id _level_; by id; run;
proc sort data=for_set; by id; run;
proc sort data=ps_data_1y; by id; run;
proc sort data=ps_data_1n_y; by id; run;
data ps_data_3;
merge for_set ps_data_1y ps_data_1n_y;
by id;
/*Inverse probability of actual exposure*/
if Exposure=0 then ipw= 1/ps_0;
if Exposure=1 then ipw= 1/ps_1;
if Exposure=2 then ipw= 1/ps_2;
if Exposure=3 then ipw= 1/ps_3;
/*Stabilized ipw: replacing numerator with marginal probability of actual exposure*/
if Exposure=0 then s_ipw= mp_0/ps_0;
if Exposure=1 then s_ipw= mp_1/ps_1;
if Exposure=2 then s_ipw= mp_2/ps_2;
if Exposure=3 then s_ipw= mp_3/ps_3;
run;
title3 "Distributions Of Propensity Scores and Weights";
proc means data=ps_data_3 mean;
class Exposure;
var ipw s_ipw;
run;
proc univariate data=ps_data_3;
var ipw s_ipw;
id id;
run;
/*Step 5: Table 1*/ /*LEFT OFF HERE*/ /*LEFT OFF HERE*/ /*LEFT OFF HERE*/ /*LEFT OFF HERE*/
/*Table 1 - Unweighted*/
title3 "Unweighted Covariate Balance Table";
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
output out = new (drop=_type_ _freq_) mean = ;
run;
proc transpose data=new out = new2 (drop=_label_) prefix = pct_; id Exposure; run;
proc sort data=new2; by _name_; run;
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
output out = new3 (drop=_type_ _freq_) std = ;
run;
proc transpose data=new3 out = new4 (drop=_label_) prefix = std_; id Exposure; run;
proc sort data=new4; by _name_; run;
data new5;
merge new2 new4;
by _name_;
mean_abs_std_diff = round(mean(
abs((pct_1 - pct_0)/sqrt(((std_1*std_1) + (std_0*std_0))/2)),
abs((pct_1 - pct_2)/sqrt(((std_1*std_1) + (std_2*std_2))/2)),
abs((pct_1 - pct_3)/sqrt(((std_1*std_1) + (std_3*std_3))/2)),
abs((pct_2 - pct_0)/sqrt(((std_2*std_2) + (std_0*std_0))/2)),
abs((pct_2 - pct_3)/sqrt(((std_2*std_2) + (std_3*std_3))/2)),
abs((pct_3 - pct_0)/sqrt(((std_3*std_3) + (std_0*std_0))/2))
), .001);
drop std_0-std_3;
run;
proc print data=new5; run;
/*Table 1 - IPW Weighted*/
title3 "IPW Weighted Covariate Balance Table";
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
weight ipw;
output out = new (drop=_type_ _freq_) mean = ;
run;
proc transpose data=new out = new2 (drop=_label_) prefix = pct_; id Exposure; run;
proc sort data=new2; by _name_; run;
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
weight ipw;
output out = new3 (drop=_type_ _freq_) std = ;
run;
proc transpose data=new3 out = new4 (drop=_label_) prefix = std_; id Exposure; run;
proc sort data=new4; by _name_; run;
data new5;
merge new2 new4;
by _name_;
mean_abs_std_diff = round(mean(
abs((pct_1 - pct_0)/sqrt(((std_1*std_1) + (std_0*std_0))/2)),
abs((pct_1 - pct_2)/sqrt(((std_1*std_1) + (std_2*std_2))/2)),
abs((pct_1 - pct_3)/sqrt(((std_1*std_1) + (std_3*std_3))/2)),
abs((pct_2 - pct_0)/sqrt(((std_2*std_2) + (std_0*std_0))/2)),
abs((pct_2 - pct_3)/sqrt(((std_2*std_2) + (std_3*std_3))/2)),
abs((pct_3 - pct_0)/sqrt(((std_3*std_3) + (std_0*std_0))/2))
), .001);
drop std_0-std_3;
run;
proc print data=new5; run;
/*Table 1 - Stabilized IPW Weighted*/
title3 "Stabilized IPW Weighted Covariate Balance Table";
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
weight s_ipw;
output out = new (drop=_type_ _freq_) mean = ;
run;
proc transpose data=new out = new2 (drop=_label_) prefix = pct_; id Exposure; run;
proc sort data=new2; by _name_; run;
proc means data=ps_data_3 noprint;
class Exposure;
var Confounder;
weight s_ipw;
output out = new3 (drop=_type_ _freq_) std = ;
run;
proc transpose data=new3 out = new4 (drop=_label_) prefix = std_; id Exposure; run;
proc sort data=new4; by _name_; run;
data new5;
merge new2 new4;
by _name_;
mean_abs_std_diff = round(mean(
abs((pct_1 - pct_0)/sqrt(((std_1*std_1) + (std_0*std_0))/2)),
abs((pct_1 - pct_2)/sqrt(((std_1*std_1) + (std_2*std_2))/2)),
abs((pct_1 - pct_3)/sqrt(((std_1*std_1) + (std_3*std_3))/2)),
abs((pct_2 - pct_0)/sqrt(((std_2*std_2) + (std_0*std_0))/2)),
abs((pct_2 - pct_3)/sqrt(((std_2*std_2) + (std_3*std_3))/2)),
abs((pct_3 - pct_0)/sqrt(((std_3*std_3) + (std_0*std_0))/2))
), .001);
drop std_0-std_3;
run;
proc print data=new5; run;
title3 "";
/*Step 6: Final Model*/
title3 "IPW Weighted Model";
proc genmod data=ps_data_3 desc;
class id Exposure (order = internal ref=first);
weight ipw;
model Outcome=Exposure/link=log dist=binomial;
repeated subject = id /type = ind;
estimate "Risk of outcome by exposure 1 v 0" Exposure 1 0 0 -1;
estimate "Risk of outcome by exposure 2 v 0" Exposure 0 1 0 -1;
estimate "Risk of outcome by exposure 3 v 0" Exposure 0 0 1 -1;
run;
proc freq data=ps_data_3;
weight ipw;
table Outcome*Exposure /chisq;
run;
title3 "Stabilized IPW Weighted Model";
proc genmod data=ps_data_3 desc;
class id Exposure (order = internal ref=first);
weight s_ipw;
model Outcome=Exposure/link=log dist=binomial;
repeated subject = id /type = ind;
estimate "Risk of outcome by exposure 1 v 0" Exposure 1 0 0 -1;
estimate "Risk of outcome by exposure 2 v 0" Exposure 0 1 0 -1;
estimate "Risk of outcome by exposure 3 v 0" Exposure 0 0 1 -1;
run;
/*Step 7: Traditional Model for Comparison*/
title3 "Traditional Log Binomial Multivariate Regression";
proc genmod data=IPW_1 desc;
class Exposure (order = internal ref=first);
model Outcome=Exposure Confounder/link=log dist=binomial;
estimate "Risk of outcome by exposure 1 v 0" Exposure 1 0 0 -1;
estimate "Risk of outcome by exposure 2 v 0" Exposure 0 1 0 -1;
estimate "Risk of outcome by exposure 3 v 0" Exposure 0 0 1 -1;
run;
title ' '; title2 ' '; title3 ' '; title4 " "; title5 " "; title6 " ";
ods rtf close;
/*********************************************************************************
* Diagnostics
*********************************************************************************/
/*Note: S_IPW and IPW weights matched what I obtained by hand a priori in Excel*/
/*Sum of Weights, 20 and 80 respectively, 1x and 4x respectively*/
/*S_IPW weights add up to the sample size, while non-standardized IPW
weights add up to t * sample size, where t = number of trt groups*/
/*proc sql;
select exposure, sum(s_ipw) as s_ipw_sum, sum(ipw) as ipw_sum
from ps_data_3
group by exposure;
quit;
/*Still, within each treatment group, the confounder distribution looks like
that of the total sample*/
/*Does the confounder distribution within each exposure group look like the
distribution in the total sample? Yes!*/
/*proc means data=ps_data_3; var confounder; title 'Unweighted'; run;
proc means data=ps_data_3; class exposure; var confounder; title 'Unweighted'; run;
proc means data=ps_data_3; class exposure; var confounder; weight s_ipw; title 'S_IPW weighted'; run;
proc freq data=ps_data_3; tables confounder; title 'Unweighted'; run;
proc freq data=ps_data_3; tables exposure*confounder; title 'Unweighted'; run;
proc freq data=ps_data_3; tables exposure*confounder; weight s_ipw; title 'S_IPW weighted'; run;
/*Does this still hold true when just looking at two groups, such as
comparing trt = 3 to trt = 0?*/
/*proc means data=ps_data_3; var confounder; where exposure in (0,3); title 'Unweighted'; run;
proc means data=ps_data_3; var confounder; weight s_ipw; where exposure in (0,3); title 'S_IPW weighted'; run;
ods rtf close;
proc datasets library=work kill;run; quit;
/*********************************************************************************
* End of Code
*********************************************************************************/