58
58
59
59
# ' @export
60
60
apm_pre <- function (models , data , weights = NULL , group_var , time_var ,
61
- val_times , unit_var , nsim = 1000 , cl = NULL ,
62
- verbose = TRUE ) {
61
+ val_times , unit_var , nsim = 1000 , cl = NULL ,
62
+ verbose = TRUE ) {
63
63
64
64
# Argument checks
65
65
chk :: chk_not_missing(models , " `models`" )
@@ -136,13 +136,25 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
136
136
}
137
137
138
138
# Fit all estimates
139
- val_data <- val_weights <- val_fits <- val_coefs <- observed_val_means <- vector(" list" , nrow(grid ))
140
-
141
- apm_mat <- mat0 <- matrix (NA_real_ ,
142
- nrow = length(val_times ),
143
- ncol = length(models ),
144
- dimnames = list (val_times ,
145
- names(models )))
139
+ val_data <- val_weights <- val_fits <- val_coefs <- vector(" list" , nrow(grid ))
140
+
141
+ # Get observed means at each time point
142
+ times <- sort(unique(data [[time_var ]]))
143
+ times <- times [times < = max(val_times )]
144
+ y <- model.response(model.frame(models [[1 ]]$ formula , data = data ))
145
+
146
+ observed_val_means <- setNames(lapply(times , function (t ) {
147
+ setNames(
148
+ vapply(group_levels , function (g ) {
149
+ mean(y [data [[time_var ]] == t & data [[group_var ]] == g ])
150
+ }, numeric (1L )),
151
+ group_levels
152
+ )
153
+ }), times )
154
+
155
+ apm_arr <- array (NA_real_ ,
156
+ dim = c(length(val_times ), length(models ), 2L ),
157
+ dimnames = list (val_times , names(models ), group_levels ))
146
158
147
159
if (verbose ) {
148
160
cat(" Fitting models..." )
@@ -171,21 +183,7 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
171
183
val_data [[f ]] <- d [subset_i ,, drop = FALSE ]
172
184
val_weights [[f ]] <- weights [subset_i ]
173
185
val_coefs [[f ]] <- na.omit(marginaleffects :: get_coef(fit ))
174
-
175
- y <- model.response(model.frame(update(mod $ formula , . ~ 1 ),
176
- data = val_data [[f ]]))
177
-
178
- if (model $ log ) {
179
- y <- exp(y )
180
- }
181
-
182
- observed_val_means [[f ]] <- setNames(
183
- vapply(group_levels , function (g ) {
184
- .wtd_mean(y , val_weights [[f ]], val_data [[f ]][[group_var ]] == g )
185
- }, numeric (1L )),
186
- group_levels
187
- )
188
-
186
+
189
187
# Compute pred error
190
188
191
189
# Compute prediction errors for each model for each validation period using original coefs
@@ -205,23 +203,26 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
205
203
group_levels
206
204
)
207
205
208
- pred_error <- (observed_val_means [[f ]][" 1" ] - observed_val_means [[f ]][" 0" ]) -
209
- (predicted_val_means_i [" 1" ] - predicted_val_means_i [" 0" ])
210
-
211
- apm_mat [t , i ] <- pred_error
206
+ for (g in group_levels ) {
207
+ apm_arr [t , i , g ] <- observed_val_means [[as.character(val_time )]][g ] - predicted_val_means_i [g ]
208
+ }
212
209
213
210
val_fits [[f ]] <- fit
214
211
215
212
grid [[" time_ind" ]][f ] <- t
216
213
grid [[" model" ]][f ] <- i
217
- f <- f + 1
214
+ f <- f + 1L
218
215
}
219
216
}
220
217
218
+ # Difference in average prediction errors
219
+ apm_mat <- apm_arr [,, " 1" ] - apm_arr [,, " 0" ]
220
+
221
221
# Simulate to get BMA weights
222
222
223
223
# # Joint variance of all model coefficients, clustering for unit
224
224
val_vcov <- vcovSUEST(val_fits , cluster = data [[unit_var ]])
225
+
225
226
if (verbose ) {
226
227
cat(" Done.\n Simulating to compute BMA weights...\n " )
227
228
}
@@ -238,14 +239,19 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
238
239
# out_mat: all prediction errors; length(times) x length(models) x nsim
239
240
out_mat <- simplify2array(pbapply :: pblapply(seq_len(nsim ), function (s ) {
240
241
241
- mat <- mat0
242
+ mat <- matrix (NA_real_ ,
243
+ nrow = length(val_times ),
244
+ ncol = length(models ),
245
+ dimnames = list (val_times , names(models )))
242
246
243
247
coefs <- sim_coefs [s ,]
244
248
245
249
for (f in seq_len(nrow(grid ))) {
246
250
i <- grid $ model [f ]
247
251
t <- grid $ time_ind [f ]
248
252
253
+ val_time <- val_times [t ]
254
+
249
255
fit <- val_fits [[f ]]
250
256
251
257
# Compute pred error
@@ -267,11 +273,9 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
267
273
}, numeric (1L )),
268
274
group_levels
269
275
)
270
-
271
- pred_error <- (observed_val_means [[f ]][" 1" ] - predicted_val_means_s_i [" 1" ]) -
272
- (observed_val_means [[f ]][" 0" ] - predicted_val_means_s_i [" 0" ])
273
-
274
- mat [t , i ] <- pred_error
276
+
277
+ mat [t , i ] <- (observed_val_means [[as.character(val_time )]][" 1" ] - observed_val_means [[as.character(val_time )]][" 0" ]) -
278
+ (predicted_val_means_s_i [" 1" ] - predicted_val_means_s_i [" 0" ])
275
279
}
276
280
277
281
mat
@@ -290,6 +294,9 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
290
294
cat(" Done.\n " )
291
295
}
292
296
297
+ observed_means <- do.call(" rbind" , observed_val_means )
298
+ rownames(observed_means ) <- names(observed_val_means )
299
+
293
300
BMA_weights <- tabulate(optimal_models , nbins = length(models )) / nsim
294
301
295
302
fits <- list (models = models ,
@@ -300,7 +307,9 @@ apm_pre <- function(models, data, weights = NULL, group_var, time_var,
300
307
val_vcov = val_vcov ,
301
308
data = data ,
302
309
weights = weights ,
303
- pred_errors = apm_mat ,
310
+ observed_means = observed_means ,
311
+ pred_errors = apm_arr ,
312
+ pred_errors_diff = apm_mat ,
304
313
BMA_weights = BMA_weights ,
305
314
nsim = nsim )
306
315
@@ -331,7 +340,7 @@ print.apm_pre_fits <- function(x, ...) {
331
340
# ' @exportS3Method summary apm_pre_fits
332
341
summary.apm_pre_fits <- function (object , order = NULL , ... ) {
333
342
out <- data.frame (bma = object $ BMA_weights ,
334
- err = apply(abs(object [[" pred_errors " ]]), 2 , max ),
343
+ err = apply(abs(object [[" pred_errors_diff " ]]), 2 , max ),
335
344
row.names = names(object $ models ))
336
345
337
346
names(out ) <- c(" BMA weights" , " Max|errors|" )
0 commit comments