将R中的日期舍入到任意精度级别

时间:2013-05-29 01:00:57

标签: r datetime rounding

我希望将R中的日期分组为任意精度。

使用例如最近的小时或分钟进行此操作是非常简单的。 lubridate

library(lubridate)
nearest_hour = floor_date(now(), 'hour')

然后,您可以将此类日期的列表分组,例如来自summarise的简单ddply plyr

我想做的是以任意精度的圆形日期,例如:到最近的15分钟或每3小时:

nearest_three_hours = floor_date(now(), '3 hours')

http://r.789695.n4.nabble.com/Truncating-dates-and-other-date-time-manipulations-td866901.html讨论了这些事情,但在截止日期之外,似乎没有任何解决方案。

任何帮助表示赞赏!谢谢。

4 个答案:

答案 0 :(得分:5)

您可以尝试此操作,仍然基于lubridate

library(lubridate)
round_minute<-function(x,precision){
  m<-minute(x)+second(x)/60
  m.r<- round(m/precision)*precision
  minute(x)<-m.r
  second(x)<-0
  x
}

round_minute(ymd_hms(c("2013-06-03 22:53:00","2013-05-03 12:18:00","2013-05-03 00:10:00")),15)

> "2013-06-03 23:00:00 UTC" "2013-05-03 12:15:00 UTC" "2013-05-03 00:15:00 UTC"

由于lubridate,代码处理了所有棘手的情况。当然,此功能仅适用于以分钟表示的精度,但您可以轻松地将其扩展到其他单位,如果您确实需要,甚至可以创建一个通用函数。

答案 1 :(得分:5)

lubridate已经到最近的原子单位。为了达到最接近的15分钟,我认为这是你想要做的事情(不是圆形),你只需要通过findInterval和一组定义的断点映射到正确的范围。试试这个floor_time,它在功能上等同于floor_date,但允许你指定一个变量#of units,包括秒,分钟或小时。

floor_time <- function(x, k = 1, unit = c("second", "minute", "hour", "day", 
                                          "week", "month", "year")) {
  require(lubridate)

  nmax <- NULL

  switch(unit, second = {nmax <- 60},
         minute = {nmax <- 60},
         hour = {nmax <- 24})

  cuts <- seq(from = 0, to = nmax - 1, by = k)
  new <- switch(unit, 
                second = update(x, seconds = cuts[findInterval(second(x), cuts)]), 
                minute = update(x, minutes = cuts[findInterval(minute(x), cuts)], 
                                seconds = 0), 
                hour = update(x, hours = cuts[findInterval(hour(x), cuts)], 
                              minutes = 0, seconds = 0), 
                day = update(x, hours = 0, minutes = 0, seconds = 0), 
                week = update(x, wdays = 1, hours = 0, minutes = 0, seconds = 0), 
                month = update(x, mdays = 1, hours = 0, minutes = 0, seconds = 0), 
                year = update(x, ydays = 1, hours = 0, minutes = 0, seconds = 0))

  new
}

答案 2 :(得分:3)

lubridate现在有一个更通用的round_date()函数。

lubridate::round_date(date, "5 mins")
lubridate::round_date(date, "2 hours")

答案 3 :(得分:3)

有点晚了,我没有代表发表评论,但正如Selva所说,lubridate现在有这个功能:

library(lubridate)
round_date(now(), '3 hours')
floor_date(now(), '3 hours')
ceiling_date(now(), '3 hours')