Search code examples
rtimeoutlapply

Is it possible for `lapply` to return partial processing results under a "timeout" constraint?


I have some code that takes a long time to execute. I am therefore using R.util's withTimeout. The synthax goes like this:

res <- withTimeout({
  v1 %>% mutate(Output = unlist(lapply(as.list(data.frame(t(v1))),function(x) 
  SomeFunction(x))))
}, timeout = 2, onTimeout = "warning")

In my code, v1 is a data frame with many rows, and the function works row-wise (using lapply). I am allowing the function to run for 2 seconds, and if it takes longer it outputs a warning. However, the output already accomplished seems to have not been saved anywhere! How do I change the code such that the output itself will be returned as well as the warning?


Solution

  • Out of curiosity I tried the following, and it seems to work well.

    ## an example data frame of 1000 columns
    ## `lapply` will loop a function over it column by column
    x <- data.frame(matrix(sample.int(2, 2 * 1000, TRUE), 2, 1000))
    
    ## actually a wrapper function of your `SomeFunction`
    ## it takes an additional `time_limit` (in seconds)
    ## is also access a GLOBAL variable `elapsed_time`
    f <- function (x, time_limit) {
      if (elapsed_time < time_limit) {
        t1 <- proc.time()[[3]]
        z <- tabulate(sample(x, 1e+5, TRUE))  ## an arbitrary example function here
        t2 <- proc.time()[[3]]
        elapsed_time <<- elapsed_time + (t2 - t1)  ## note the `<<-`
        } else {
        z <- NULL
        }
      z
      }
    
    elapsed_time <- 0                  ## elapsed time counter (in global environment)
    oo <- lapply(x, f, time_limit = 2) ## 2 seconds time limit
    
    elapsed_time
    #[1] 2.002
    
    sum(sapply(oo, is.null))
    #[1] 693
    

    So on my laptop, the iteration terminates after (1000 - 693) = 307 rounds. lapply still returns a length 1000 list, but only the first 307 elements hold the processing result, while the remaining 693 entries are NULL.

    Actually, this serves a good example where <<- would be useful.