попробуй поймать внутри dplyr mutate? - PullRequest
0 голосов
/ 14 мая 2018

Есть ли механизм исключения в dplyr mutate()? Я имею в виду способ ловить исключения и обрабатывать их.

Предположим, что у меня есть функция, которая в некоторых случаях выдает ошибку (в примере, если входной сигнал отрицательный), для простоты я определяю функцию, но в реальной жизни это будет функция в некоторых R пакет. Предположим, что эта функция векторизована:

# function throwing an error
my_func <- function(x){
  if(x > 0) return(sqrt(x))
  stop('x must be positive')
}

my_func_vect <- Vectorize(my_func)

Теперь предположим, что я хочу использовать эту функцию внутри mutate().

Если эта функция используется внутри mutate(), она останавливается на первой ошибке и результат не возвращается:

library(dplyr)
# dummy data
data <- data.frame(x = c(1, -1, 4, 9))
data %>% mutate(y = my_func_vect(x))
# Error in mutate_impl(.data, dots) : Evaluation error: x must be positive.

Есть ли способ отловить ошибку и что-то сделать (например, вернуть NA) в этом случае, получая результаты для других элементов?

Результат, который я ожидаю, - это то, чего можно достичь, используя цикл с tryCatch(), то есть что-то вроде:

y <- rep(NA_real_, length(data$x))
for(i in seq_along(data$x)) {
  tryCatch({
    y[i] <- my_func_vect(data$x[i])
  }, error = function(err){})
}
y
# Result is: 1 NA 2 4

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Мы также можем использовать функции purrr safely() или possibly().

Из справки purrr:

безопасно : вместо этого упакованная функция возвращает список с компонентом result и error.Одно значение всегда НЕДЕЙСТВИТЕЛЬНО.

спокойно : вместо этого функция с переносом возвращает список с компонентами результат, выходные данные, сообщения и предупреждения.

возможно :Обернутая функция использует значение по умолчанию (в противном случае) при возникновении ошибки.

Это не меняет того факта, что вы должны применять функцию к каждой строке отдельно.

library(dplyr)
library(purrr)

# function throwing an error
my_func <- function(x){
  if(x > 0) return(sqrt(x))
  stop('x must be positive')
}

my_func_vect <- Vectorize(my_func)

# dummy data
data <- data.frame(x = c(1, -1, 4, 9))

С картой:

data %>% 
  mutate(y = map_dbl(x, ~possibly(my_func_vect, otherwise = NA_real_)(.x)))
#>    x  y
#> 1  1  1
#> 2 -1 NA
#> 3  4  2
#> 4  9  3

Использование rowwise():

data %>%
  rowwise() %>% 
  mutate(y = possibly(my_func_vect, otherwise = NA_real_)(x))
#> Source: local data frame [4 x 2]
#> Groups: <by row>
#> 
#> # A tibble: 4 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     1
#> 2    -1    NA
#> 3     4     2
#> 4     9     3

Другие функции несколько сложнее использовать и применять в «среде фрейма данных», так как онибольше подходит для работы со списками и возвращает такие.

Создано в 2018-05-15 пакетом представлением (v0.2.0).

0 голосов
/ 14 мая 2018

Вы хотите оценивать каждую возникающую ошибку отдельно, возможно, вам не следует использовать векторизованную функцию. Вместо этого используйте map из пакета purrr, что фактически совпадает с lapply здесь.

Создайте функцию для отлова ошибки для стандартного использования, если вам нужны значения NA в случае, если вы получаете ошибку.

try_my_func <- function(x) {
  tryCatch(my_func(x), error = function(err){NA})
}

Затем используйте mutate с map

data %>% mutate(y = purrr::map(x, try_my_func))
   x  y
1  1  1
2 -1 NA
3  4  2
4  9  3

Или аналогичным образом, если вы не хотите объявлять новую функцию.

data %>% mutate(y = purrr::map(x, ~ tryCatch(my_func(.), error = function(err){NA})))

И, наконец, если вы хотите использовать функцию векторизации, вы можете вообще пропустить функцию map. Но лично я никогда не использую Vectorize, поэтому я бы сделал это с map.

data %>% mutate(y = Vectorize(try_my_func)(x))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...