r语言 - 防止在dplyr::if_else中同时计算yes和no而产生不必要的警告



类似base::ifelse, dplyr::if_else计算两个"yes"one_answers";no"(参见线程2和线程3)。这可能会给出一个讨厌的警告,我想用这种条件方法来避免:我正在尝试根据数据输入格式(在这种情况下:日期)有条件地解析。

但是我怎样才能避免这些警告呢?我不想要suppressWarnings,因为我仍然希望在解析完全失败时有警告(我包括了一个示例,其中就是这种情况)

library(lubridate)
library(dplyr)
x <- c("20/01/2001", "02/28/01", "2000/01/01")
# Both if_else and case_when evaluate for all conditions
if_else(nchar(x) > 8, dmy(x), mdy(x))
#> Warning: 2 failed to parse.
#> Warning: 2 failed to parse.
#> [1] "2001-01-20" "2001-02-28" NA
case_when(nchar(x) > 8 ~ dmy(x), TRUE ~ mdy(x))
#> Warning: 2 failed to parse.
#> Warning: 2 failed to parse.
#> [1] "2001-01-20" "2001-02-28" NA

我认为你建议在ifelse(和dplyr::if_elsedata.table::fifelse)内短路逻辑,我没有看到一种方法可以安全地在所有用例中做到这一点。例如,认识到dmy(x)是一个单个函数调用,其参数为向量;实现短路需要ifelse替换函数知道x向量的子集,并且只在需要它的元素上调用dmy。虽然可以指定需要以这种方式处理的符号看起来合乎逻辑,但这开始使它变得有点复杂。

我认为在这里真正做类似短路处理的最好方法是有点手动,自己控制矢量化元素。

out <- rep(Sys.Date()[NA], length(x))
for (fun in list(dmy, mdy)) {
isna <- is.na(out)
if (all(!isna)) break
out[isna] <- fun(x[isna])
}
# Warning:  2 failed to parse.
# Warning:  1 failed to parse.
out
# [1] "2001-01-20" "2001-02-28" NA          

可以在多个函数(不只是2个)上迭代,也可以在单个函数的参数上迭代(例如尝试使用as.POSIXct或类似的格式)。(多于两个会更接近dplyr::case_when而不是ifelse/dplyr::if_else…这是case_when的设计优势之一。

每次通过for循环,只有那些仍然在out中产生NA的元素在下一步被处理;一旦非NA,该元素就是"safe"再也不碰了。一旦所有的out都不是NA,即使没有使用其他候选函数/格式,循环也会中断。

这仍然存在ifelse的一个元素是累积计算的问题,要求在它之前存在整个向量。这需要更多的逻辑和控制,并且将在执行之前排除测试的短路。(在第一次循环或for循环之前进行累积计算会有所帮助。没有示例,我希望您可以看到这里潜在的复杂性。

最新更新