Search code examples
rdata.tablelubridate

What is the efficient way to round/floor ITime-formated time from data.table library


What is the efficient way to round/floor ITime-formated time from data.table library?

The way I convert it is: I transform it to POSIXct, floor the result, and then convert it back to ITime. Example

library(lubridate)
library(data.table)

# Suppose I have some ITime variable:
Time = as.ITime( Sys.time() )

#That's what I do:
as.ITime( floor_date( as.POSIXct( Time ), "5 minutes"), format = "%H:%M:%S")

#Result:
[1] "16:05:00"

That works OK, but does not seem efficient because of the double converting. Is there a good alternative?


Solution

  • You could use the fact that an ITime variable is internally stored as an integer (number of seconds).

    library(lubridate)
    library(data.table)
    
    # Let generate an ITime variable
    
    set.seed(233)
    y <- as.ITime(sample(60*60*24, size = 1e6, replace = TRUE))  # 60*60*24: max number of seconds in a day 
    

    because 5 minutes are 60 * 5 seconds (300 seconds), you could divide your variable by 300, take its floor and then multiply back by 300. You can use the integer division operator, %/%, for the first two steps.

    # head of the data using this method  and the one you suggested:
    head(data.table(
        y = y,
        method1 = (y %/% 300L) * 300L,
        method2 = as.ITime( floor_date( as.POSIXct( y ), "5 minutes"), format = "%H:%M:%S")),
        n = 10)
      
               y  method1  method2
     1: 13:21:33 13:20:00 13:20:00
     2: 13:24:11 13:20:00 13:20:00
     3: 18:02:47 18:00:00 18:00:00
     4: 20:06:51 20:05:00 20:05:00
     5: 19:59:35 19:55:00 19:55:00
     6: 16:35:46 16:35:00 16:35:00
     7: 16:32:10 16:30:00 16:30:00
     8: 15:57:35 15:55:00 15:55:00
     9: 01:21:16 01:20:00 01:20:00
    10: 17:10:09 17:10:00 17:10:00
    

    Timing

    microbenchmark::microbenchmark(
      method1 = (y %/% 300L) * 300L,
      method2 = as.ITime( floor_date( as.POSIXct( y ), "5 minutes"), format = "%H:%M:%S"),
      times = 5L
    )
    
    Unit: milliseconds
        expr      min       lq      mean   median       uq      max neval
     method1   7.5192   7.7691   8.23544   8.0286   8.8695   8.9908     5
     method2 396.5867 404.5420 418.07694 412.6798 436.3783 440.1979     5