背景
我有一个计算昂贵(和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
or FALSE
,昂贵的函数都会运行,这使得我的脚本运行起来非常缓慢。
深入挖掘 if_else、ifelse 和 case_when
我知道向量化的 if/else 语句if_else
和ifelse
(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
返回一个未计算的表达式,然后我稍后会在适当的时间进行计算(有点像冻干函数调用),这可能是解决方案的一部分。但到目前为止还没有快乐。
有什么我错过了轻松做我想做的事吗?或者有人可以提供一些关于实施的提示吗?谢谢!