0

背景

我有一个计算昂贵(和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_elsecase_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_
  )
}

问题是无论条件评估为TRUEor FALSE,昂贵的函数都会运行,这使得我的脚本运行起来非常缓慢。

深入挖掘 if_else、ifelse 和 case_when

我知道向量化的 if/else 语句if_elseifelse(and case_when) 不像传统的 if...else 语句那样工作;评估语句的所有部分,然后使用条件将要返回的结果拼接在一起。例如,此代码产生以下输出和警告:

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

[1] 2 1 1 2

警告信息:

1:在 ifelse(v > 0, log10(v), log10(-v)) 中:产生 NaN

2:在 ifelse(v > 0, log10(v), log10(-v)) 中:产生了 NaN

条件为真时的返回值和条件为假时的返回值都被评估,并且条件用于将结果向量拼接在一起。

因此,我昂贵且缓慢的功能运行的次数比实际需要的要多得多。

我怎样才能避免这种情况?

我想要什么

我正在寻找替代的矢量化实现,if_else并且case_when仅在条件为真时评估结果为真。

到目前为止我尝试过的

我尝试编写自己的if_else/向量化实现ifelse,但没有成功。我也尝试过非标准评估,但我知道的不够多,无法完成这项工作。我猜如果我可以if_else返回一个未计算的表达式,然后我稍后会在适当的时间进行计算(有点像冻干函数调用),这可能是解决方案的一部分。但到目前为止还没有快乐。

有什么我错过了轻松做我想做的事吗?或者有人可以提供一些关于实施的提示吗?谢谢!

4

0 回答 0