【问题标题】:Get days between start and end date without weekend and + - span获取开始日期和结束日期之间的天数,不包括周末和 + - 跨度
【发布时间】:2018-02-20 16:58:22
【问题描述】:

现在我有一个新问题。我需要计算两个日期之间的时间跨度。我的问题是:必须排除周末,时间跨度可以是负数或正数。 例如:

Planed delivery Real delivery  
2017-11-28     2018-11-17  
2016-05-10     2016-09-22 
2016-06-08     2016-11-07   
2016-07-08     2016-06-07

等等。 我有以下代码可以做到这一点:

getDuration <- function(date_scheduled, date_received,fmt="%Y-%m-%d") {
    myDays <- ifelse(date_received > date_scheduled,
                    seq.Date(to   = as.Date(date_received, format=fmt), 
                       from = as.Date(date_scheduled, format =fmt), 
                       by   = 1),
                     seq.Date(to   = as.Date(date_scheduled, format=fmt), 
                        from = as.Date(date_received, format =fmt), 
                        by   = 1))
     length(myDays[!is.weekend(myDays)])
}

当我使用命令时:

getDataPart(prep_DPM_All_new$Goods_received_date, prep_DPM_All_new$Schedule_Line_Delivery)

我收到以下错误:

Error in seq.Date(to = as.Date(date_received, format = fmt), from = as.Date(date_scheduled,  :'from' must be of length 1 

起初我认为日期列的格式不正确,但我认为它看起来不错。

str(prep_DPM_All_new$Goods_received_date)
 POSIXct[1:33078], format: "2016-03-24"  
str(prep_DPM_All_new$Schedule_Line_Delivery)
 POSIXct[1:33078], format: "2016-03-29"

谁能帮我解释一下,为什么我会收到错误消息? 如果没有 if else 语句,我得到了错误,即“错误的登录方式”。

输出应该是这样的:

Row 1: 254  
Row 2: 109   
Row 3:  98   
Row 4: -24  

我试图通过对类似问题使用一些解决方案来解决问题,但这些问题只有正值。我认为负值是主要问题。

【问题讨论】:

  • 您希望从上表中得到什么结果?
  • 第 1 行:254,第 2 行:109,第 3 行:98,第 4 行:-24
  • 请您仔细检查一下预期的结果。我相信第 2 行和第 3 行的结果已经交换。

标签: r date timespan weekend


【解决方案1】:

seq.Date() 在这里有点棘手,原因有两个:

  1. 该函数未矢量化,即只允许使用单值参数。
  2. fromtoby 参数必须对应,即,如果 to 低于 from,则 by 必须为负数。

这是一个按行号分组来解决问题 1 的解决方案。并使用 sign()range() 函数来解决问题 2。此外,使用了 chron 包,OP 从中获取了is.weekend()函数。

library(data.table)
library(chron)
# coerce to data.table and chron
DF <- setDT(DF)[, lapply(.SD, chron, format = "y-m-d")]
DF[, rn := .I][, {
  s <- sign(Actual_delivery - Planned_delivery)
  r <- range(Actual_delivery, Planned_delivery)
  .(diff.working.days = s * sum(!is.weekend(seq(r[1], r[2]))))
}, by = rn]
   rn diff.working.days
1:  1               254
2:  2                98
3:  3               109
4:  4               -24

数据

library(data.table)
DF <- fread(
  "Planned_delivery Actual_delivery  
2017-11-28     2018-11-17  
2016-05-10     2016-09-22 
2016-06-08     2016-11-07   
2016-07-08     2016-06-07"
)

【讨论】:

  • 疯狂的解决方案! O.o 没想到做这么“简单”的任务竟然这么复杂。 :/ 不过,你能解释一下,这个函数是如何工作的吗?我从未见过“。”在字母前面,(好吧,我也是 R 的新手)以及声明“:=”(而我是从另一种编程语言中知道的)。
  • 您的所有问题都可以通过data.table方式得到解答。这份备忘单可能会有所帮助:s3.amazonaws.com/assets.datacamp.com/blog_assets/…
  • 在 R 中,您通常有不同的选项来实现相同的结果。这是data.table 语法,我更喜欢分组。请参阅github.com/Rdatatable/data.table/wiki/Getting-started 上的小插曲和常见问题解答。
  • 你好,我有一个新的问题。当我尝试它时,我必须使用字符而不是列的日期格式。是否有可能将公式转换为日期格式而不是字符?我还有一些其他公式可以访问这些日期格式列。果仁蛋糕:)。
猜你喜欢
  • 2021-12-17
  • 2011-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多