有没有办法反过来做 align.time() 之类的事情?

Is there a way to do something like align.time() in reverse?

我有多个数据变量,每 15 分钟收集一次,但是一些变量的时间戳略有偏差,因为各种传感器的内部时钟没有完全对齐。为了轻松合并各种测量值,我想将所有时间戳对齐到最接近的 15 分钟标记。

我想使用类似 xts::align.time() 的函数,但是这个函数总是快进。我希望能够向后捕捉,或者更好的是,使用智能舍入规则。我该怎么做?

这是我想使用 align.time():

执行的示例代码
require(xts)
require(dplyr)

timestamps <- as.data.frame(as.POSIXlt.character(c("2017-09-11 00:01:39", 
"2017-09-11 00:16:39", "2017-09-11 00:31:39", "2017-09-11 00:46:39"), tz 
= "", format = "%Y-%m-%d %H:%M:%S"))
values <- as.data.frame(as.numeric(c(1,2,6,0.5)))
variable <- as.data.frame(rep("Chloride", 4))

df <- cbind(timestamps, values, variable); names(df) <- c("DateTime_UTC", 
"Value", "Variable")

df %>%
  mutate(DateTime_UTC = align.time(DateTime_UTC, n = 60 * 15))

>        DateTime_UTC Value Variable
>1 2017-09-11 00:15:00   1.0 Chloride
>2 2017-09-11 00:30:00   2.0 Chloride
>3 2017-09-11 00:45:00   6.0 Chloride
>4 2017-09-11 01:00:00   0.5 Chloride

但是我更喜欢时间快照来产生这个:

>        DateTime_UTC Value Variable
>1 2017-09-11 00:00:00   1.0 Chloride
>2 2017-09-11 00:15:00   2.0 Chloride
>3 2017-09-11 00:30:00   6.0 Chloride
>4 2017-09-11 00:45:00   0.5 Chloride

我看过 align.time,您需要的版本是 align.time.POSIXct。现在我假设你可以提供负数 n,但你不能。

但是您可以做两件事,创建您自己的 align.time 函数或使用 lubridate 包中的 floor_date。这将四舍五入到最近的单位。检查 ?floor_date 所有可能的选项。

创建您自己的函数就像我在下面所做的一样。我刚刚从 align.time.POSIXct 中删除了负限制并创建了函数 my_align_time.

my_align_time <- function(x, n = 60) {
  structure(unclass(x) + (n - unclass(x) %% n), class=c("POSIXct","POSIXt"))
}

library(lubridate)
library(dplyr)

df %>%
  mutate(use_floor_date = floor_date(DateTime_UTC, unit = "15 mins"),
         use_my_align_time = my_align_time(DateTime_UTC, n = 60 * -15))

         DateTime_UTC Value Variable           use_floor        use_my_align
1 2017-09-11 00:01:39   1.0 Chloride 2017-09-11 00:00:00 2017-09-11 00:00:00
2 2017-09-11 00:16:39   2.0 Chloride 2017-09-11 00:15:00 2017-09-11 00:15:00
3 2017-09-11 00:31:39   6.0 Chloride 2017-09-11 00:30:00 2017-09-11 00:30:00
4 2017-09-11 00:46:39   0.5 Chloride 2017-09-11 00:45:00 2017-09-11 00:45:00

当然,现在的问题是哪个更快?使用 1000 个时间戳,结果是使用对齐函数要快得多,与 floor_date 相比,记录越多,速度就越快。当然 floor_date 里面有很多检查来检查日期时间对象是否正确、单位检查等。

library(microbenchmark)
x <- Sys.time() + 1:1000

microbenchmark(floor = floor_date(x, unit = "15 mins"),
               align = my_align_time(x, n = -60 * 100))

Unit: microseconds
  expr      min       lq       mean   median       uq      max neval
 floor 4598.913 4670.447 4738.57723 4728.228 4781.770 5188.149   100
 align   25.454   27.210   32.61044   31.305   33.646   75.484   100