Open In App

TryCatch with parLapply (Parallel package) in R

Last Updated : 20 Jun, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

R has a useful function called ‘tryCatch’ that enables you to handle errors and warnings that could happen while your code is being executed. When combined with the parallel package function ‘parLapply’, which parallelly applies a function to each member of a list, you can run many instances of your code at once and manage any problems or warnings that may come up as each iteration is being executed.

  • R’s ‘tryCatch’ function enables you to detect and deal with problems and warnings that could appear while your code is being executed. The function requires two arguments: the expression to be evaluated and a list of handlers outlining what should be done in the event of an error or warning.
  • The R Programming Language function ‘parLapply’ applies a function in parallel to each member of a list using the parallel package. The list to be processed, the function to apply to each element of the list, and the number of cores to be used for parallel processing are the three arguments required by the function.

Here is an illustration of how to process a list of inputs in parallel using tryCatch and parLapply.

R




library(parallel)
  
# To handle errors and warnings, write
# a function containing tryCatch clauses.
my_function <- function(x) {
  tryCatch({
    # Code that needs to be run for each list element
    result <- sqrt(x)
    return(result)
  }, error = function(e) {
    # code that will be executed in the event of an error
    return(NA)
  }, warning = function(w) {
    #code that will be executed in the event of a warning
    return(NA)
  })
}
  
# Build a cluster object.
cl <- makeCluster(2)
  
# Make a list of the inputs that
# will be handled concurrently.
inputs <- list(1, 2, 3, 4, 5)
  
# Apply the function in parallel to
# each entry of the list.
results <- parLapply(cl, inputs, my_function)
  
# Put an end to the cluster
stopCluster(cl)
  
# Print the outcomes
print(results)


Output:

1
1.414214
1.732051
2
2.236068
  • The function  ‘my_function’ in this example is defined with ‘tryCatch’ statements to deal with errors and warnings. Then, we use ‘parLapply’  to parallelize the application of the function ‘my_function’ to each element of the list of inputs to be processed.
  • The cluster object ‘cl ‘ produced by the ‘makeCluster()’ method is supplied as the first argument to the ‘parLapply()’ function in this version. The ‘stopCluster()’ function is used to stop the cluster after processing is finished.
  • The’ barplot()’ function is included towards the conclusion. The nested list of results is transformed into a flat vector and provided to barplot using the ‘unlist()’  method.(). Xlab, Ylab, and main are used to label the axes and the title of the chart, while the ‘names.arg’  argument is used to label the bars with the inputs.

Let’s say we want to use the ‘parLapply’ function to compute the median for each vector in a collection of numeric vectors. One of the vectors does, however, contain a character value that the median algorithm is unable to handle. ‘TryCatch’ will be used to handle the error, and ‘NA’ will be returned for the associated output list element. Here is an illustration of how to do it. Another instance where the code’s error section executes is as follows:

R




library(parallel)
  
# make a cluster with 4 nodes.
cl <- makeCluster(4)
  
# create a function to determine a
# numeric vector's median
compute_median <- function(x) {
  tryCatch({
    return(median(x))
  }, error = function(e) {
    return(NA)
  })
}
  
# create a collection of numerical vectors 
# for which the median should be calculated.
x_list <- list(c(11, 12, 13), 
               c(14, 15, 16), 
               c("a", "b", "c"), 
               c(17, 18, 19))
  
# Using parLapply, compute the medians in
# parallel, and tryCatch to manage errors 
medians <- parLapply(cl, x_list, compute_median)
  
# shut the cluster
stopCluster(cl)
  
# print the medians
print(medians)


Output:

[[1]]
[1] 12

[[2]]
[1] 15

[[3]]
[1] "b"

[[4]]
[1] 18

In this example, the first and second elements of the input list were processed successfully and returned the expected median values of 12 and 15, respectively. The third element of the input list resulted in an error due to the presence of character values, and the ‘error’ part of the ‘tryCatch’ function was executed, returning ‘NA’ for that element. Finally, the fourth element of the input list was processed successfully and returned the expected median value of 18.

Handling Missing Numbers

Let’s say we want to substitute the missing values in each column of a data frame with the mean value for that column. TryCatch will be used to manage any potential errors, and an error message will be returned. Here is an illustration of how to do it:
 

R




# put missing numbers in a data frame:
df <- data.frame(x = c(11, 12, 13, NA, 15),
                 y = c(NA, 12, 13, 14, 15))
  
# create a function that replaces missing
# numbers with the column's mean value.
replace_missing_values <- function(x) {
  tryCatch({
    return(ifelse(is.na(x),
                  mean(x,
                       na.rm = TRUE),
                  x))
  }, error = function(e) {
    return("Error: Unable to replace missing values")
  })
}
  
# Lapply is used to fill in each column's 
# missing values, and tryCatch is used to
# manage errors.
df_imputed <- as.data.frame(lapply(df,
                                   replace_missing_values))
  
# for display the generated data frame
print(df_imputed)


Output:

      x    y
1 11.00 13.5
2 12.00 12.0
3 13.00 13.0
4 12.75 14.0
5 15.00 15.0

In this instance, the ‘replace_missing_values’ code first uses the ‘is.na’ function to see if the input vector contains any missing values.(x). ‘Mean(x, na.rm = TRUE)’ is used to replace any numbers that are missing with the mean value of that column. If there are any problems, the ‘tryCatch’ function’s error section is called and returns an error message.

Managing File Read Failures

Let’s say we have a collection of file paths, and we want to use the readLines function to read the contents of each file into a list. We want to use tryCatch to manage the error and return an error message when one of the files does not exist. Here is an illustration of how to do it: 

R




# establish a list of file paths
file_paths <- c("file1.txt", "file2.txt",
                "file3.txt")
  
# create a function to read a file's data
read_file_contents <- function(file_path) {
  tryCatch({
    return(readLines(file_path))
  }, error = function(e) {
    return(paste("Error: Unable to read file",
                 file_path))
  })
}
  
# using lapply, read each file's text into 
# a list, and using tryCatch to deal with errors.
file_contents <- lapply(file_paths,
                        read_file_contents)
  
# outcome the file contents
print(file_contents)


Output:

[[1]]
[1] "Error: Unable to read file file1.txt"

[[2]]
[1] "Error: Unable to read file file2.txt"

[[3]]
[1] "Error: Unable to read file file3.txt"

In the given example, “the read_file_contents” function first tries to use “readLines(file_path)” to read the contents of the input file. If there are any problems, the “tryCatch” function’s “error” section is called and returns an error message.

Correcting a Division-by-Zero Mistake

Consider dividing a vector of numbers by a constant value, but the constant value is zero. We want to use “tryCatch” to manage the division by zero error and return an error message. Here is an illustration of how to do it.

R




# Construct a vector of numbers
numbers <- c(1, 2, 3, 4, 5)
  
# A function that divides each number
# by a variable should be created.
div_by_variable <- function(x, var) {
  if(var == 0){
    stop("Error: Not able to divide by 0")
  } else {
    return(x/var)
  }
}
  
# Utilizing parLapply, apply the function to 
# the numbers vector with a zero-valued variable.
library(parallel)
cl <- makeCluster(2)
result <- tryCatch({
  parLapply(cl, numbers, div_by_variable, 
            var = 0)
}, error = function(e) {
  message("Error: Not able to divide by 0")
})
  
# Halt the cluster
stopCluster(cl)
  
# print the result
if(inherits(result, "try-error")) {
  message(result)
} else {
  print(result)
}


Output:

Error: Not able to divide by 0
NULL

This output shows that there was a problem with the “parLapply” function’s computation. The divide function encountered a division by zero issue, as indicated by the error message “Error: Not able to divide by 0” sent to the console. No output was returned and the value of output is “NULL” because the stop function was used to terminate the function with an error.

Conclusion

In R, the ‘tryCatch’ function is used to manage errors that might happen while a block of code is being executed. The try argument, which contains the code to be run, and the catch argument, which contains a function to handle errors, are the two primary arguments that the function accepts. You can use the catch method to do a number of things, like print an error message, return a default value, or run an alternative code block. The code block is performed in parallel on various cores when ‘tryCatch’ is combined with ‘parLapply’ from the parallel package in R, enabling faster code execution.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads