-
Notifications
You must be signed in to change notification settings - Fork 0
/
concord-6.2.stan
174 lines (142 loc) · 4.82 KB
/
concord-6.2.stan
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
// Concordance model 6.2: Include the "income" noisy measure of SES.
// In this version we assume that the mean SES is still the best predictor for the
// medicaid and admission status.
functions {
real logodds(data int [] X, data int N) {
real Nx = sum(X);
real px = Nx / N;
print("\tNx: ", Nx, " px: ", px, " logit(px): ", logit(px));
return logit(px);
}
real posh_logit(real logit_osh, real logit_elect, real logit_ed) {
return inv_logit(logit_osh - (logit_elect + logit_ed));
}
}
data {
int<lower=0> N;
int<lower=1, upper=4> SPEC[N];
int<lower=1, upper=3> ADM[N];
int<lower=0, upper=1> W[N];
int<lower=0, upper=1> S[N];
int<lower=0, upper=1> H[N];
int<lower=0, upper=1> C[N];
int<lower=0, upper=1> O[N];
int<lower=0, upper=1> D[N];
vector[N] I;
}
transformed data {
real ao0;
real ad0;
vector[3] aa0; // base rate for each type of admission (OSH, elective, ED)
int ADMx[N,3]; // one-hot representation of admission status
print("Calc ao0");
ao0 = logodds(O, N); // base rate outcome
print("Calc ad0");
ad0 = logodds(D, N); // base rate medicaid
print("ad0 = ", ad0);
for(j in 1:3) {
int A[N];
for(i in 1:N) {
A[i] = (SPEC[i] == 1);
}
aa0[j] = logodds(A, N);
}
for(i in 1:N) {
for(j in 1:3) {
ADMx[i,j] = 0;
}
ADMx[i, ADM[i]] = 1;
}
}
parameters {
vector[4] aspc; // SPEC effect on concordance
real bwc; // weekend effect on concordance
real bsu; // sex effect on mean SES
real<upper=0> bhu; // HNW effect on mean SES
real bud; // SES effect on medicaid, presumed positive (together with the
// sign convention below, this implies higher SES lowers the prob.
// of being enrolled in medicaid.
real ad; // base rate medicaid
vector[3] bua; // SES effect on ADM
vector[3] aadm;
vector[4] aspo; // SPEC effect on outcome
real bwo; // weekend effect on outcome
real bco; // concordance effect on outcome
real bso; // sex effect on outcome
real bho; // HNW effect on outcome
real buo; // SES effect on outcome. I think this can be assumed to be 1,
// since it only appears when multiplied by another parameter, never
// by itself.
vector[3] aao; // ADM effect on outcome
real<lower=0> sigi; // scale factor for I residuals to the mean SES
}
model {
vector[N] SES_mean; // latent socioeconomic status
vector[N] pO; // accumulator variable for outcome probability
vector[N] ptmp; // accumulator for other var probabilities.
// priors for all parameters
aspc ~ normal(0, 0.5);
bwc ~ normal(0, 0.5);
bsu ~ normal(0, 0.5);
bhu ~ normal(0, 0.5);
bua ~ normal(0, 0.5);
aadm ~ normal(aa0, 0.25);
bud ~ normal(0, 0.5);
ad ~ normal(0, 0.25);
aspo ~ normal(0, 0.5);
bwo ~ normal(0, 0.5);
bco ~ normal(0, 0.5);
bso ~ normal(0, 0.5);
bho ~ normal(0, 0.5);
buo ~ normal(0, 0.5);
aao ~ normal(0, 0.5);
sigi ~ exponential(0.5);
// With N random effects, only N-1 of them are independent, so put a soft constraint on
// one of them. In this case we choose ED admission effect on outcome.
aao[3] ~ normal(0, 0.01); // ED is the baseline for admission effect on outcome
// latent SES variable
for (i in 1:N) {
SES_mean[i] = bsu*S[i] + bhu*H[i];
}
I ~ normal(SES_mean, sigi); // Noisy, but direct measurement of SES
// medicaid: base rate + SES effect.
for (i in 1:N) {
ptmp[i] = ad0 + ad - bud*SES_mean[i]; // Effect of higher SES presumed to be negative.
if (is_nan(ptmp[i])) {
print("NaN val found: SES_mean = ", SES_mean[i], " ad = ", ad, " ad0 = ", ad0, " bud = ",
bud);
}
}
D ~ bernoulli_logit(ptmp);
// concordance: random effect for specialty, plus weekend effect
for (i in 1:N) {
ptmp[i] = aspc[SPEC[i]] + bwc*W[i];
}
C ~ bernoulli_logit(ptmp);
// Admission type
for(i in 1:N) {
ADMx[i] ~ multinomial_logit(aadm + bua*SES_mean[i]);
}
// outcome
for (i in 1:N) {
pO[i] = aspo[SPEC[i]] + bwo*W[i] + bco*C[i] + bso*S[i] + bho*H[i] +
buo*SES_mean[i] + aao[ADM[i]];
}
O ~ bernoulli_logit(pO);
}
generated quantities {
real ADCE_H; // Average direct causal effect of H
{
real SES_mean; // reconstruct SES -- Is it possible to make this a transformed parameter?
real lp0; // logit of p when H==0
vector[N] p_h0; // p(O | do(H==0))
vector[N] p_h1; // p(O | do(H==1))
for (i in 1:N) {
SES_mean = bsu*S[i] + bhu*H[i];
lp0 = aspo[SPEC[i]] + bwo*W[i] + bco*C[i] + bso*S[i] + buo*SES_mean + aao[ADM[i]];
p_h0[i] = inv_logit(lp0);
p_h1[i] = inv_logit(lp0 + bho*H[i]);
}
ADCE_H = mean(p_h1 - p_h0);
}
}