首页 > 解决方案 > 防止在 dplyr::if_else 中计算 yes 和 no 导致的不希望出现的警告

问题描述

与 base::ifelse 一样,dplyr::if_else 计算“是”和“否”的结果(另请参见线程 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

标签: rdplyr

解决方案


ifelse我认为您是在(and dplyr::if_elseand )内建议短路逻辑data.table::fifelse,我看不出有一种方法可以在所有用例中安全地做到这一点。例如,意识到这dmy(x)是一个以向量作为参数的单个函数调用;实现短路需要-replacement 函数知道对向量进行子集化,并仅在需要它的元素上调用它。虽然人们可能会认为可以指定需要以这种方式处理的符号是合乎逻辑的,但这开始让它变得有点复杂。ifelsexdmy

我认为在这里真正进行类似短路处理的最佳方法是手动控制矢量化元素。

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之一的。)ifelsedplyr::if_elsecase_when

每次通过for循环时,只有那些仍然产生NAin的元素out在下一步中被处理;一旦 non- NA,该元素是“安全的”并且不会再次被触及。一旦 all 都不outNA,即使未使用更多候选函数/格式,循环也会中断。

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


推荐阅读