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?
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
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