[英]In a dataframe with a date column in POSIXct format, what is the date associated to a specific number in another column?
[英]How to calculate the number of a specific weekday between two POSIXct date arrays and return another numerical array?
我根据工作日计算算法编写了一个公式(在Stackexchange中也可以找到,很棒的工作人员。这是代码片段:
countwd <- function(start, end, day){
x <- seq(start, end, by=1)
y <- weekdays(x, TRUE)
sum(y==day)
}
x$OFFDAY <- NULL
for(i in 1:nrow(x)){
x$OFFDAY[i] <- countwd(x$PICK_DATE[i], x$SHIP_DATE[i], "Mon")
}
这太慢了(循环继续像每秒2-4行!!!!),我每个月有数百万条目。
这是函数的矢量化:
x$OFFDAY <- countwd(x$PICK_DATE, x$SHIP_DATE, "Mon")
显示此错误:
seq.POSIXt中的错误(start,end,by = 1):'from'必须长度为1
在这种情况下我无法理解如何应用“apply”系列函数,因为我有两个要比较的向量(是的,我对此很新)。
样本数据:
PICK_DATE SHIP_DATE
01-APR-2017 00:51 02-APR-2017 06:55 AM
01-APR-2017 00:51 02-APR-2017 12:11 PM
01-APR-2017 00:51 02-APR-2017 12:11 PM
01-APR-2017 00:51 02-APR-2017 09:39 AM
我已将这些转换为POSIXct,并且该公式适用于单个值(但返回第二个值,不知道为什么。但是,我可以解决这个问题):
>countwd(x$PICK_DATE[1], x$SHIP_DATE[1], "Mon")
[1] 0
向量化多个变化输入函数的简单方法是使用mapply
:
mapply(countwd, x$SHIP_DATE, x$PICK_DATE, "Mon")
或者,您可以使用sapply
并传递一系列索引作为第一个参数(这种方式的语法非常类似于for
循环:
sapply(1:nrow(x), function(i) countwd(x$SHIP_DATE[i], x$PICK_DATE[i], "Mon"))
然而,你的情况下主要的低效率来自countwd
函数。 请注意,您正在将POSIXt
向量传递给函数。 因此,当在函数的第一行中调用seq
时, by
参数被认为是秒而不是几天! 这导致产生不必要的大向量(详情请参见?seq.POSIXt
)。
以下列方式更改countwd
应该可以大大提高性能:
countwd <- function(start, end, day) {
x <- seq(start, end, by="day")
y <- weekdays(x, TRUE)
sum(y==day)
}
另请注意, weekdays
是特定于语言环境的,可能无法按预期工作,具体取决于您的语言环境设置。
根据@ demirev的回答和我上面的评论,这是一个使用改进的countwd
函数和mapply
的工作示例。 我使用lubridate
输入了几个辅助列来检查解决方案,并更改了一些日期以将值返回到非零的df$off_days
。
library(lubridate)
df <- data.frame(pick_date = c(rep("01-APR-2017 00:51", 4)), ship_date = c("05-APR-2017 06:55", "09-APR-2017 12:11", "30-APR-2017 12:11", "02-MAY-2017 12:11"))
df$pick_date <- lubridate::dmy_hm(df$pick_date)
df$ship_date <- lubridate::dmy_hm(df$ship_date)
df$pick_day <- wday(df$pick_date, label = T)
df$ship_day <- wday(df$ship_date, label = T)
df$days_between <- interval(df$pick_date, df$ship_date) %/% days()
countwd <- function(start, end, day) {
x <- seq(start, end, by="day")
y <- weekdays(x, TRUE)
sum(y==day)
}
df$off_days <- mapply(countwd, df$pick_date, df$ship_date, "Mon")
df
pick_date ship_date pick_day ship_day days_between off_days
1 2017-04-01 00:51:00 2017-04-05 06:55:00 Sat Wed 4 1
2 2017-04-01 00:51:00 2017-04-09 12:11:00 Sat Sun 8 1
3 2017-04-01 00:51:00 2017-04-30 12:11:00 Sat Sun 29 4
4 2017-04-01 00:51:00 2017-05-02 12:11:00 Sat Tues 31 5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.