R ifelse 在 dplyr 中跨评估条件它不应该

问题描述 投票:0回答:1

注意:

我修复了我的代表。

我有一个

ifelse
语句作为
across
中的函数。即使在条件为真的情况下,我在尝试计算下降值时也会出错。

library(tidyverse)

tibble(x = 1:3) %>%
  mutate(y = across(x, ~ifelse(.x==1, 1, days_in_month(.x-1))))
#> Error in `mutate()`:
#> ℹ In argument: `y = across(x, ~ifelse(.x == 1, 1, days_in_month(.x -
#>   1)))`.
#> Caused by error in `across()`:
#> ! Can't compute column `x`.
#> Caused by error in `month.numeric()`:
#> ! Values are not in 1:12
#> Backtrace:
#>      ▆
#>   1. ├─tibble(x = 1:3) %>% ...
#>   2. ├─dplyr::mutate(...)
#>   3. ├─dplyr:::mutate.data.frame(...)
#>   4. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), by)
#>   5. │   ├─base::withCallingHandlers(...)
#>   6. │   └─dplyr:::mutate_col(dots[[i]], data, mask, new_columns)
#>   7. │     └─mask$eval_all_mutate(quo)
#>   8. │       └─dplyr (local) eval()
#>   9. ├─dplyr::across(x, ~ifelse(.x == 1, 1, days_in_month(.x - 1)))
#>  10. │ ├─base::withCallingHandlers(...)
#>  11. │ └─fn(col, ...)
#>  12. │   ├─base::ifelse(.x == 1, 1, days_in_month(.x - 1))
#>  13. │   └─lubridate::days_in_month(.x - 1)
#>  14. │     ├─lubridate::month(x, label = TRUE, locale = "C")
#>  15. │     └─lubridate:::month.numeric(x, label = TRUE, locale = "C")
#>  16. │       └─base::stop("Values are not in 1:12")
#>  17. └─base::.handleSimpleError(...)
#>  18.   └─dplyr (local) h(simpleError(msg, call))
#>  19.     └─rlang::abort(bullets, call = error_call, parent = cnd)

tibble(x = 1:3) %>%
  rowwise() %>%
  mutate(y = ifelse(x==1, 1, days_in_month(x-1)))
#> # A tibble: 3 × 2
#> # Rowwise:
#>       x     y
#>   <int> <dbl>
#> 1     1     1
#> 2     2    31
#> 3     3    28

创建于 2023-10-24,使用 reprex v2.0.2

r dplyr tidyverse lubridate
1个回答
0
投票

我之前在

mutate()
中使用函数时遇到过类似的问题。我认为问题在于
mutate
本身如何工作,因为
days_in_month()
抛出错误的唯一实例是当
x=1
不应该根据条件进行评估,但它似乎在
 评估整个列本身days_in_month(.x-1)

所以就像

rowwise()
的工作原理一样,我在将条件函数传递给
across()
之前对其进行向量化。

library(tidyverse)

foo=function(x){
  ifelse(x==1, 1, days_in_month(x-1))
}

foo = Vectorize(foo)

tibble(x = 1:3) %>%
  mutate(y = across(x, ~foo(x)))
© www.soinside.com 2019 - 2024. All rights reserved.