为什么我的自定义函数在改变 tibble 时不起作用?
我创建了一个自定义函数来将工作日添加到日期。该函数依赖于以下包:
library(tidyverse)
library(lubridate)
library(tidyquant)
这是我创建的函数:
add_workingdays <- function(start_date, number_of_days, switch_count_weekendsholidays = TRUE, remove_weekends = TRUE, holidays = NULL){
start_date <- start_date %>% as.Date()
if (!is.Date(start_date)) stop("add_workingdays(): start_date must be a date.", call. = FALSE)
target_date <- start_date + number_of_days
if(switch_count_weekendsholidays){
target_date_lenght <- tidyquant::WORKDAY_SEQUENCE(start_date, target_date, remove_weekends, holidays = holidays) %>% length()
while(target_date_lenght != number_of_days) {
target_date <- target_date + 1
target_date_lenght <- tidyquant::WORKDAY_SEQUENCE(start_date, target_date, remove_weekends, holidays = holidays) %>% length()
}
}
target_date %>% return()
}
当我在以下场景中运行该函数时,它可以正常工作。
add_workingdays(start_date = '2022-04-08' %>% as.Date(), number_of_days = 5)
[1] "2022-04-14"
'2022-04-08' %>% as.Date() %>% add_workingdays(number_of_days = 5)
[1] "2022-04-14"
但是当我尝试在 tibble 的 mutate 函数中使用它时,我收到了我不理解的错误消息。
我使用以下代码,最后给出错误:
tibble(
+ dates = rep('2022-04-08' %>% as.Date()), #) seq.Date(from = '2022-04-08' %>% as.Date(), by = 'days', length.out = 5),
+ days_to_add = rep(10:5)
+ ) %>%
+ print() %>%
+ mutate(
+ target_date = add_workingdays(start_date = dates, number_of_days = days_to_add)
+ )
# A tibble: 6 x 2
dates days_to_add
<date> <int>
1 2022-04-08 10
2 2022-04-08 9
3 2022-04-08 8
4 2022-04-08 7
5 2022-04-08 6
6 2022-04-08 5
Error in `mutate()`:
! Problem while computing `target_date =
add_workingdays(start_date = dates, number_of_days =
days_to_add)`.
Caused by error in `seq.Date()`:
! 'from' must be of length 1
Run `rlang::last_error()` to see where the error occurred.
任何人都可以向我解释在 mutate 函数中使用此自定义函数时我做错了什么吗?
I created an custom function to add working days to a date. The function depends on the following packages:
library(tidyverse)
library(lubridate)
library(tidyquant)
This is the function I created:
add_workingdays <- function(start_date, number_of_days, switch_count_weekendsholidays = TRUE, remove_weekends = TRUE, holidays = NULL){
start_date <- start_date %>% as.Date()
if (!is.Date(start_date)) stop("add_workingdays(): start_date must be a date.", call. = FALSE)
target_date <- start_date + number_of_days
if(switch_count_weekendsholidays){
target_date_lenght <- tidyquant::WORKDAY_SEQUENCE(start_date, target_date, remove_weekends, holidays = holidays) %>% length()
while(target_date_lenght != number_of_days) {
target_date <- target_date + 1
target_date_lenght <- tidyquant::WORKDAY_SEQUENCE(start_date, target_date, remove_weekends, holidays = holidays) %>% length()
}
}
target_date %>% return()
}
When I run the function in the following scenario, it works without problems.
add_workingdays(start_date = '2022-04-08' %>% as.Date(), number_of_days = 5)
[1] "2022-04-14"
'2022-04-08' %>% as.Date() %>% add_workingdays(number_of_days = 5)
[1] "2022-04-14"
But when I try to use it within a mutate
function in a tibble, I get error messages I do not understand.
I use the following code and it gives the error at the end:
tibble(
+ dates = rep('2022-04-08' %>% as.Date()), #) seq.Date(from = '2022-04-08' %>% as.Date(), by = 'days', length.out = 5),
+ days_to_add = rep(10:5)
+ ) %>%
+ print() %>%
+ mutate(
+ target_date = add_workingdays(start_date = dates, number_of_days = days_to_add)
+ )
# A tibble: 6 x 2
dates days_to_add
<date> <int>
1 2022-04-08 10
2 2022-04-08 9
3 2022-04-08 8
4 2022-04-08 7
5 2022-04-08 6
6 2022-04-08 5
Error in `mutate()`:
! Problem while computing `target_date =
add_workingdays(start_date = dates, number_of_days =
days_to_add)`.
Caused by error in `seq.Date()`:
! 'from' must be of length 1
Run `rlang::last_error()` to see where the error occurred.
Can anyone explain to me what I do wrong when using this custom function within a mutate function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该错误与
mutate
无关。它来自于tidyquant::WORKDAY_SEQUENCE
函数中的参数输入不正确。如果您通过将其打印到控制台来检查此函数,您会得到以下信息:这表明此函数使用
DATE_SEQUENCE
函数。同样,如果您检查此函数,您会发现它使用seq.Date
函数,该函数需要from
参数为单个日期。例如:如果您向
from
输入多个日期数据,您会收到相同的错误:为避免此错误,当您想要输入
start_date
的列时,您必须对WORKDAY_SEQUENCE
函数进行矢量化,这意味着您将该函数应用于列中的每个日期。正如@danloo所示,您可以使用Vectorize
。您还可以使用*apply
系列。情况 1:
start_date
为多个日期,end_date
为单个日期。在这种情况下,您可以使用
lapply
或sapply
。您还需要对
length()
函数进行矢量化。由于lapply
返回一个列表,因此如果您需要返回一个向量以便可以使用它在数据框中创建列,则可以使用unlist()
:因此,如果您想遵循上面的
lapply
方法,则应将函数中的相关行修改为情况 2:
start_date
都有多个日期和结束日期
在这种情况下,您可以使用
Map
或mapply
The error has nothing to do with
mutate
. It comes from the improper input for the argument in thetidyquant::WORKDAY_SEQUENCE
function. If you check this function by printing it to the console, you get this:which shows that this function uses
DATE_SEQUENCE
function. Likewise, if you check this function, you'll find that it usesseq.Date
function, which requires a single date for thefrom
argument. For example:If you entry more than one date data to
from
, you get the same error:To avoid this error, when you want to entry a column for
start_date
, you have to vectorize theWORKDAY_SEQUENCE
function, which means you apply the function to each date in the column. As @danloo shows, you can useVectorize
. You can also use*apply
family.Case 1 : multiple dates for
start_date
and a single date forend_date
.In this case, you can use
lapply
orsapply
.You also need to vectorize
length()
function. Becauselapply
returns a list, if you need to return a vector so that it can be used to create a column in a data frame, you can useunlist()
:Hence, if you'd like to follow the
lapply
method above, the relevant line in your function should be revised fromto
Case 2 : multiple dates for both of
start_date
andend_date
In this case, you can use
Map
ormapply
您的函数必须使用
Vectorize
进行矢量化,或者使用purrr::map
或lapply
单独应用于每个元素:创建于 2022 年- 04-13 由 reprex 包 (v2.0.0)
Your function must be either vectorized using
Vectorize
or applied to each element individually usingpurrr::map
orlapply
:Created on 2022-04-13 by the reprex package (v2.0.0)