hdkrgr
hdkrgr

Reputation: 1736

r: Retaining warnings in `sapply` loop as a vector

I'm transforming my data using my own function as following:

my_df %>% [...] %>%
  mutate(my_result = sapply(id_column, my_function))

Here, my_function will perform some computation for each row that returns a numeric result. The function cannot (easily) be vectorized, which is why I'm relying on sapply. So far, so good.

Sometimes, my_function will throw a warning, indicating that a specific result should be taken with a grain of salt.

I would like to capture these warnings, and append them to my dataframe in a new column. Expected result:

id_column | ... | result | warnings 1 | ... | result1 | NA 2 | ... | result2 | "Warning: something happened on id 2" 3 | ... | result3 | NA

How can I achieve this?

Upvotes: 1

Views: 278

Answers (2)

hdkrgr
hdkrgr

Reputation: 1736

An alternative to @mpjdem's answer but staying with sapply:

tryCatch.W.E returns a list

>> tryCatch.W.E(log(-5))
$value
[1] NaN
$warning
<simpleWarning in log(-5): NaNs produced>

In conjunction with sapplythis results in a matrix and the original task can be solved by

my_df %>% cbind(t(sapply(.$id_column, function(x) {tryCatch.W.E(my_function(x))})))

Upvotes: 0

mpjdem
mpjdem

Reputation: 1544

I'd use lapply instead, so you can return a one-row data.frame with two columns each time and rbind that list of data frames again at the end.

df <- data.frame(a=runif(20)-0.5)

f <- function(x) {
    tryCatch ({
        data.frame(result=log(x), warning=NA)
    }, warning = function(w) {
        data.frame(result=suppressWarnings(log(x)), warning=w$message)
    })
}

res <- cbind(df, do.call(rbind, lapply(df$a, f)))

Upvotes: 2

Related Questions