99# ' ecological inference is run.
1010# '
1111# ' This function wraps around the ei function from the ei R package. This
12- # ' function is unstable and can break in apparently arbitrary ways. Errors
12+ # ' function is unstable and can break in arbitrary ways. Errors
1313# ' often emerge with particular values of the erho parameter. If the function
1414# ' breaks, it will automatically try adjusting the erho parameter, first to 20,
1515# ' then to 0.5.
4444# ' output.
4545# '
4646# ' @importFrom doSNOW registerDoSNOW
47- # ' @importFrom foreach getDoParWorkers
47+ # ' @importFrom foreach getDoParWorkers %dopar% %do%
4848# ' @importFrom bayestestR ci
4949# ' @importFrom purrr lift
5050# ' @importFrom utils capture.output setTxtProgressBar
@@ -87,7 +87,7 @@ ei_iter <- function(
8787 }
8888
8989 # Standard to use 1 less core for clusters
90- clust <- parallel :: makeCluster(parallel :: detectCores() - 1 )
90+ clust <- makeCluster(parallel :: detectCores() - 1 )
9191
9292 # Register parallel processing cluster
9393 doSNOW :: registerDoSNOW(clust )
@@ -133,7 +133,9 @@ ei_iter <- function(
133133 }
134134 }
135135
136- if (verbose ) message(paste(" Beginning" , n_iters , " 2x2 estimations..." ))
136+ if (verbose ) {
137+ message(paste(" Beginning" , n_iters , " 2x2 estimations..." ))
138+ }
137139
138140 # Init progressbar
139141 pb <- utils :: txtProgressBar(
@@ -146,9 +148,10 @@ ei_iter <- function(
146148
147149 # Loop through each 2x2 ei
148150 ei_results <- foreach :: foreach(
149- i = 1 : n_iters ,
151+ i = seq_len( n_iters ) ,
150152 .inorder = FALSE ,
151- .packages = c(" ei" , " stats" , " utils" ),
153+ .packages = c(" ei" , " stats" , " utils" , " mvtnorm" ),
154+ .export = c(" ei_sim" , " .samp" , " like" , " .createR" ),
152155 .options.snow = opts
153156 ) %myinfix % {
154157 cand <- race_cand_pairs [i , " cand" ]
@@ -161,103 +164,61 @@ ei_iter <- function(
161164 set.seed(seed )
162165
163166 # Run 2x2 ei
164- # Calls to ei are wrapped in nested try-catches that try different erho
165- # parameters to get the function working. The underlying ei function is
166- # unstable and changing erho can break it.
167- tryCatch(
168- {
169- utils :: capture.output({
170- ei_out <-
171- suppressMessages(
172- purrr :: lift(ei :: ei )(
173- data = data ,
174- formula = formula ,
175- total = totals_col ,
176- erho = erho ,
177- simulate = TRUE ,
178- args_pass
167+ # This loop tries three different erho values before returning an error.
168+ # It first tries the default erho value, then the default for ei (0.5),
169+ # then 20.
170+ erhos <- c(erho , 0.5 , 20 )
171+ ii <- 1
172+ while (ii < 4 ) {
173+ tryCatch(
174+ {
175+ utils :: capture.output({
176+ ei_out <-
177+ suppressMessages(
178+ purrr :: lift(ei :: ei )(
179+ data = data ,
180+ formula = formula ,
181+ total = totals_col ,
182+ erho = erhos [ii ],
183+ simulate = TRUE ,
184+ args_pass
185+ )
179186 )
180- )
181- })
182-
183- # This was meant to enable parameterization of the ei importance sample
184- # size, but its inclusion changes results dramatically.
185- # utils::capture.output({
186- # ei_out <- suppressMessages(ei_sim(ei_out, samples))
187- # })
188- },
189- error = function (cond ) {
190- message(paste(
191- format(formula ),
192- " iteration failed. Retrying with erho = 20...\n "
193- ))
194- tryCatch(
195- {
196- utils :: capture.output({
197- ei_out <-
198- suppressMessages(
199- purrr :: lift(ei :: ei )(
200- data = data ,
201- formula = formula ,
202- total = totals_col ,
203- erho = 20 ,
204- simulate = TRUE ,
205- args_pass
206- )
187+ })
188+ break
189+ # This was meant to enable parameterization of the ei importance sample
190+ # size, but its inclusion changes results dramatically.
191+ # utils::capture.output({
192+ # ei_out <- suppressMessages(ei_sim(ei_out, samples))
193+ # })
194+ },
195+ error = function (cond ) {
196+ if (ii == 3 ) {
197+ stop(
198+ message(
199+ paste(
200+ format(formula ),
201+ " iteration failed three times. Error on third failure:\n " ,
202+ cond ,
203+ " Type ?ei_iter for guidance on how to proceed."
207204 )
208- })
209-
210- # This was meant to enable parameterization of the ei importance
211- # sample size, but its inclusion changes results dramatically.
212- # utils::capture.output({
213- # ei_out <- suppressMessages(ei_sim(ei_out, samples))
214- # })
215- },
216- error = function (cond ) {
205+ )
206+ )
207+ } else {
208+ ii <- ii + 1
217209 message(
218210 paste(
211+ " \n " ,
219212 format(formula ),
220- " iteration failed again. Retrying with erho = 0.5...\n "
213+ " iteration failed. Retrying with erho =" ,
214+ as.character(erhos [ii ]),
215+ " ..."
221216 )
222217 )
223- tryCatch(
224- {
225- utils :: capture.output({
226- ei_out <-
227- suppressMessages(
228- purrr :: lift(ei :: ei )(
229- data = data ,
230- formula = formula ,
231- total = totals_col ,
232- erho = 20 ,
233- simulate = TRUE ,
234- args_pass
235- )
236- )
237- })
238-
239- # This was meant to enable parameterization of the ei importance
240- # sample size, but its inclusion changes results dramatically.
241- # utils::capture.output({
242- # ei_out <- suppressMessages(ei_sim(ei_out, samples))
243- # })
244- },
245- error = function (cond ) {
246- stop(paste(
247- formula ,
248- " failed with the following error:\n " ,
249- cond ,
250- " Try a different erho parameter." ,
251- " If the problem persists, please submit an issue on the" ,
252- " eiCompare git repository, including the error you" ,
253- " received."
254- ))
255- }
256- )
257218 }
258- )
259- }
260- )
219+ }
220+ )
221+ }
261222
262223 # Plots to be added here
263224 if (plots ) {
@@ -302,8 +263,8 @@ ei_iter <- function(
302263 # This works according to the aggregate formula in King, 1997, section 8.3
303264 aggs <- res $ aggs
304265 ses <- c()
305- for (i in 1 : ncol(aggs )) {
306- aggs_col <- aggs [, i ]
266+ for (k in 1 : ncol(aggs )) {
267+ aggs_col <- aggs [, k ]
307268 m <- mean(aggs_col )
308269 nsims <- length(aggs_col )
309270 devs <- m - aggs_col
@@ -333,15 +294,13 @@ ei_iter <- function(
333294 list (district_res , precinct_res , aggs_b , list (race , cand , ei_out ))
334295 }
335296
336- # if (par_compute == TRUE) {
337- # # Stop clusters (always done between uses)
338- # parallel::stopCluster(clust)
339- # # Garbage collection (in case of leakage)
340- # gc()
341- # #setTxtProgressBar(pb, i)
342- #
343- # return(ei_out)
344- # }
297+ # Stop clusters as soon as done parallel processing
298+ if (par_compute ) {
299+ # Stop clusters (always done between uses)
300+ stopCluster(clust )
301+ # Garbage collection (in case of leakage)
302+ gc()
303+ }
345304
346305 # close progress bar
347306 close(pb )
@@ -352,12 +311,6 @@ ei_iter <- function(
352311 agg_results <- sapply(ei_results , function (x ) x [3 ])
353312 ei_objects <- sapply(ei_results , function (x ) x [4 ])
354313
355- if (par_compute ) {
356- # Stop clusters (always done between uses)
357- parallel :: stopCluster(clust )
358- # Garbage collection (in case of leakage)
359- gc()
360- }
361314
362315 # Put results in dataframe
363316 results_table <- get_results_table(
0 commit comments