Векторизованная конструкция if / else, позволяющая избежать вызова дорогой функции, когда условие имеет значение FALSE? - PullRequest
0 голосов
/ 14 сентября 2018

Фон

У меня есть вычислительно дорогая (и SLOW ) функция, которая вызывается из другой функции, которая является частью конвейера dplyr:

dat %>%
mutate_at(.vars = vars(dplyr::intersect(starts_with("locale"), ends_with("last_name"))), 
          .funs = funs(native_last_name_alpha(., Type))) %>% 
          {.} -> dat

Функция выполняет одно из двух действий, в зависимости от того, совпадает ли переменная Type (строка символов) для "мужской" или "женский". Если есть совпадение, native_last_name_alpha запустит вычислительно дорогую и медленную функцию, которая выполняет некоторые другие вещи. Если совпадений нет, native_last_name_alpha вернет NA. В настоящее время, поскольку это векторизация, я использую if_else и case_when, чтобы определить, что должно произойти, например:

native_last_name_alpha <- function(locale, type) {
  case_when(
    type == "male" ~ stringi::stri_trans_toupper(
      fake_single_alpha(locale = locale, 
                        request = "last_name_male", 
                        provider = "faker.providers.person")
    ),
    type == "female" ~ stringi::stri_trans_toupper(
      fake_single_alpha(locale = locale, 
                        request = "last_name_female", 
                        provider = "faker.providers.person")
    ),
    TRUE ~ NA_character_
  )
}

Проблема в том, что дорогая функция запускается независимо от того, оценивается ли условие как TRUE или FALSE, и это делает мой скрипт чрезвычайно медленным для запуска.

Копание глубже в if_else, ifelse и case_when

Я понимаю, что векторизованные операторы if / else if_else и ifelsecase_when) не работают как традиционные операторы if ... else; все части оператора оцениваются, а затем условие используется для объединения результатов, которые должны быть возвращены. Например, этот код выдает следующие выходные данные и предупреждения:

v <- c(-100, -10, 10, 100)
ifelse(v > 0, log10(v), log10(-v))

[1] 2 1 1 2

Предупреждающие сообщения:

1: In ifse (v> 0, log10 (v), log10 (-v)): произведено NaN

2: In ifse (v> 0, log10 (v), log10 (-v)): произведено NaN

Как возвращаемое значение, если условие истинно, так и возвращаемое значение, если условие ложно, оцениваются, и условие используется для соединения вектора результатов.

Следовательно, моя дорогая и медленная функция работает намного больше, чем требуется.

Как мне избежать этого?

Что бы я хотел

Я ищу альтернативные векторизованные реализации if_else и case_when, которые оценивают результат result-if-true, когда условие истинно.

Что я пробовал до сих пор

Я пытался написать свои собственные векторизованные реализации if_else / ifelse, но безуспешно. Я также экспериментировал с нестандартной оценкой, но я не знаю достаточно, чтобы сделать эту работу. Я предполагаю, что если я смогу получить if_else, чтобы возвратить неоцененное выражение, которое я затем вычислю позже в соответствующее время (вроде как вызов функции сублимационной сушкой), это может быть частью решение. Но пока радости нет.

Я что-то упустил, чтобы легко делать то, что я хочу? Или кто-то может предложить некоторые советы по реализации? Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...