【问题标题】:If time in datetime is midnight 00:00:00 change to next day如果 datetime 中的时间是午夜 00:00:00 更改为第二天
【发布时间】:2019-12-07 21:16:18
【问题描述】:

我正在为时间序列分析设置一个大型数据集。数据具有日期开始时间和日期结束时间。

数据输入为结束时间的 24:00:00,我现在已将其转换为 00:00:00。我想将在 00:00:00 完成的所有最终数据向前移动一天。

#Current database
id<-c("m1","m1","m1","m2","m2","m2","m3","m4","m4")
x<-c("2020-01-03 10:00:00","2020-01-03 16:00:00","2020-01-03 
19:20:00","2020-01-05 10:00:00","2020-01-05 15:20:00","2020-01-05 
20:50:00","2020-01-06 06:30:00","2020-01-08 06:30:00","2020-01-08 
07:50:00")
start<-strptime(x,"%Y-%m-%d %H:%M:%S")
y<-c("2020-01-03 16:00:00","2020-01-03 19:20:00","2020-01-03 
00:00:00","2020-01-05 15:20:00","2020-01-05 20:50:00","2020-01-05 
00:00:00","2020-01-06 07:40:00","2020-01-08 07:50:00","2020-01-08 
08:55:00")
end<-strptime(y,"%Y-%m-%d %H:%M:%S")
mydata<-data.frame(id,start,end)

#Output
id2<-c("m1","m1","m1","m2","m2","m2","m3","m4","m4")
x2<-c("2020-01-03 10:00:00","2020-01-03 16:00:00","2020-01-03 
19:20:00","2020-01-05 10:00:00","2020-01-05 15:20:00","2020-01-05 
20:50:00","2020-01-06 06:30:00","2020-01-08 06:30:00","2020-01-08 
07:50:00")
start2<-strptime(x2,"%Y-%m-%d %H:%M:%S")
y2<-c("2020-01-03 16:00:00","2020-01-03 19:20:00","2020-01-04 
00:00:00","2020-01-05 15:20:00","2020-01-05 20:50:00","2020-01-06 
00:00:00","2020-01-06 07:40:00","2020-01-08 07:50:00","2020-01-08 
08:55:00")
end2<-strptime(y2,"%Y-%m-%d %H:%M:%S")
mydata2<-data.frame(id2,start2,end2)

我希望第 3 行和第 6 行的输出将日期提前一天。是“if”函数还是有更简单的方法?

【问题讨论】:

    标签: r time time-series


    【解决方案1】:

    if 看起来很简单。 ifelse 被矢量化了:

    library(lubridate)
    mydata$end2 = as_datetime(ifelse(format(mydata$end, "%H:%M:%S") == "00:00:00", mydata$end + days(1), mydata$end), tz = Sys.timezone())
    mydata
    #   id               start                 end                end2
    # 1 m1 2020-01-03 10:00:00 2020-01-03 16:00:00 2020-01-03 16:00:00
    # 2 m1 2020-01-03 16:00:00 2020-01-03 19:20:00 2020-01-03 19:20:00
    # 3 m1 2020-01-03 19:20:00 2020-01-03 00:00:00 2020-01-04 00:00:00
    # 4 m2 2020-01-05 10:00:00 2020-01-05 15:20:00 2020-01-05 15:20:00
    # 5 m2 2020-01-05 15:20:00 2020-01-05 20:50:00 2020-01-05 20:50:00
    # 6 m2 2020-01-05 20:50:00 2020-01-05 00:00:00 2020-01-06 00:00:00
    # 7 m3 2020-01-06 06:30:00 2020-01-06 07:40:00 2020-01-06 07:40:00
    # 8 m4 2020-01-08 06:30:00 2020-01-08 07:50:00 2020-01-08 07:50:00
    # 9 m4 2020-01-08 07:50:00 2020-01-08 08:55:00 2020-01-08 08:55:00
    

    【讨论】:

      【解决方案2】:

      正如您所要求的“更简单的方式”:lubridate 包会自动为您执行此操作(即使是超过 24:00:00 的时间)。如果您不熟悉它,请查看 RStudio 网站上的 cheatsheet

      以 00:00:00 结尾的日期时间将保持在同一天,以 24:00:00 结尾的日期时间将向前跳一天。一些例子:

      library(lubridate)
      
      ymd_hms("2019-07-30 00:00:00")
      [1] "2019-07-30 UTC"
      
      ymd_hms("2019-07-30 24:00:00")
      [1] "2019-07-31 UTC"
      
      ymd_hms("2019-07-30 24:01:05")
      [1] "2019-07-31 00:01:05 UTC"
      

      我真的推荐使用这个包,因为它使处理日期时间的麻烦大大减少。在一致性与性能之间有一个小的权衡,但我认为在大多数情况下这不是问题。

      【讨论】:

        【解决方案3】:

        如果数据在POSIXct 中,则添加86400 相当于添加一天。您可以将其向量化,而不是使用 if 语句。

        library(lubridate)
        my_hours <- rep(0, nrow(mydata))
        my_hours[which(hour(mydata$end)==0)] <- 86400
        my_hours <- which(hour(mydata$end) == 0)
        mydata$end <- mydata$end + my_hours
        
        mydata$end == mydata2$end2
        [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
        

        【讨论】:

        • 可能会遇到闰秒问题?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-23
        相关资源
        最近更新 更多