Ограничение времени обработки функции в цикле R for

Я хочу применить функцию ("foo" для этого объяснения), чтобы преобразовать вектор данных в другое значение. Эта функция принимает данные в качестве входных данных и должна отправлять формы на веб-страницы. Иногда это происходит быстро, а иногда - долго. Я хотел бы запустить цикл for (или эквивалентную функцию apply) таким образом, чтобы пропустить элементы, которые занимают слишком много времени. Я попытался ограничить время выполнения цикла перед переходом к следующим 5 секундам, используя следующее:

pb <- txtProgressBar(min = 1, max = 100, style = 3)
storage <- matrix(nrow = sample.length, ncol = 2)

for(i in 1:100){  
     s <- Sys.time()  
     storage[i,] <- try(foo(data.vec[i]), TRUE)  
     if (Sys.time() - s >5) {next}  
     # update progress bar  
     setTxtProgressBar(pb, i)  
}  
close(pb)  

Я думаю, что я не должен понимать, как применять условие 'next' в цикле for. искал, чтобы найти более ясное объяснение, но не получал никакой удачи здесь.

2 ответа

Решение

evalWithTimeout() из пакета R.utils, совместно с tryCatch(), может обеспечить более чистое решение.

Например:

require(R.utils)

for(i in 1:5) {
    tryCatch(
        expr = {
            evalWithTimeout({Sys.sleep(i); cat(i, "\n")}, 
                            timeout = 3.1)
            }, 
        TimeoutException = function(ex) cat("Timeout. Skipping.\n")
    )
}

# 1 
# 2 
# 3 
# Timeout. Skipping.
# Timeout. Skipping.

В искусственном примере выше:

  • Первый аргумент evalWithTimeout() содержит код для оценки в каждом цикле.

  • timeout аргумент evalWithTimeout() устанавливает ограничение по времени в секундах.

  • TimeoutException аргумент tryCatch() принимает функцию, которая должна быть выполнена, когда время итерации цикла истекло.

Я работаю над тем, чтобы заставить цикл работать в foreach с %dopar%, поэтому запуск сообщения об ошибке вызвал у меня головную боль, так как это разорвет цикл.

Я каждый раз создаю переменную skip, и когда происходит тайм-аут, цикл переходит к следующей итерации. Надеемся, что вы избежите «остановки» или «перерыва» при использовании с партнерскими функциями.

          for(i in 1:5) {
     res=NULL
     skip=FALSE
    tryCatch(
      {res= withTimeout({Sys.sleep(i); 
       cat(i, "\n")},  timeout = 3.1, 
       onTimeout='error')
        }, 
     TimeoutException = function(ex){skip <<- 
        TRUE})
    if(skip){next}
}
Другие вопросы по тегам