【问题标题】:Comparing time series with different timestamps in R在 R 中比较具有不同时间戳的时间序列
【发布时间】:2020-11-23 12:57:17
【问题描述】:

我遇到的问题如下:

  • 正在观察多个过程并记录更改
  • 我们只有变化的时间和观察值
  • 由于两个时间序列都没有相同的时间戳集,因此无法直接比较它们
  • 但我们知道,除非记录了变化,否则观察值保持不变

我们如何检查在某个时间点在所有流程中观察到了哪些值? 我们如何根据已知信息生成定期汇总(例如平均每日值)?

这是数据的模型:

tsVector1 <- c("2020-01-01 16:18", "2020-01-03 12:12", "2020-01-03 14:56", "2020-01-10 09:48", "2020-01-11 23:00")
tsVector2 <- c("2020-01-01 16:18", "2020-01-02 14:10", "2020-01-04 18:36", "2020-01-06 19:23", "2020-01-10 21:10")
tsVector3 <- c("2020-01-01 16:18", "2020-01-05 13:37", "2020-01-08 01:11")
obsVector1 <- c(1, 1.2, 1.6, 3, 3.8)
obsVector2 <- c(1, 1.4, 1.7, 1.8, 2.1)
obsVector3 <- c(1:3)
procVector1 <- rep("proc1", 5)
procVector2 <- rep("proc2", 5)
procVector3 <- rep("proc3", 3)
tsDF <- data.frame(ts = as.POSIXct(c(tsVector1, tsVector2, tsVector3)),
                   observation = c(obsVector1, obsVector2, obsVector3), 
                   process = c(procVector1, procVector2, procVector3))

我正在寻找这样的输出:

SomeHelpfulFunction(tsDF, "2020-01-07 01:00")
>  process  observation
> process1  1.6
> process2  1.8
> process3  2.0

有没有一种方法可以在不使用循环或复制所有被比较的时间序列中的所有唯一时间戳的情况下获取这些数据?


更新: 在查看了回复并使用更大的数据集对其进行测试后,我发现data.table 方法最适合我的用例,并且还可以加快响应时间。为了给你一个想法,我测量的时间是:

  • 33.46s - data.table
  • 49.36s - 基础 R duplicated()
  • 219.53s - dplyr 使用 top_n() 而不是 slice_tail()

【问题讨论】:

    标签: r time-series


    【解决方案1】:

    这是一个在data.table 中使用滚动连接的可爱解决方案:

    library(data.table)
    
    SomeHelpfulFunction <- function(tsDF, time) {
      a = data.table(tsDF,
                     key=c("process", "ts"))
      b = data.table(process = unique(tsDF$process),
                     ts = as.POSIXct(time),
                     key = c("process", "ts"))
      a[b, roll=TRUE]
    }
    
    SomeHelpfulFunction(tsDF, "2020-01-07 1:00")
    #>                     ts observation process
    #> 1: 2020-01-07 01:00:00         1.6   proc1
    #> 2: 2020-01-07 01:00:00         1.8   proc2
    #> 3: 2020-01-07 01:00:00         2.0   proc3
    

    我发现这篇博文有助于解释滚动连接:https://r-norberg.blogspot.com/2016/06/understanding-datatable-rolling-joins.html

    【讨论】:

      【解决方案2】:

      我认为对于每个进程,您都需要查询时间之前的最后一个值。与dplyr

      library(dplyr)
      
      tsDF %>% 
        group_by(process) %>% 
        arrange(ts) %>% 
        filter(ts <= "2020-01-07 01:00") %>% 
        slice_tail() %>% 
        ungroup() %>% 
        select(-ts)
      

      给了

      # A tibble: 3 x 2
        observation process
              <dbl> <fct>  
      1         1.6 proc1  
      2         1.8 proc2  
      3         2   proc3  
      

      【讨论】:

      • 您好,感谢您的回复,很遗憾我无法安装dplyr 的源代码版本,并且二进制版本(0.8.5)似乎不包含slice_tail(),所以这个解决方案可能是对处于类似情况的人有问题
      • 嗨 bmonger,对于旧版本的 dplyr,您可以将 slice_tail 替换为 top_n(1, ts)
      【解决方案3】:

      我发现了另一种单独使用基础 R 实现 ruslt 的方法。但它依赖于duplicated(),仅适用于获取最后一次读数,因此不适用于需要最后 N 次读数的应用程序:

      SomeHelpfulFunction <- function(tsDF, time) {
          functionLocalDF <- tsDF[order(tsDF$process, tsDF$ts), ]
          functionLocalDF <- functionLocalDF[functionLocalDF$ ts <= time, ]
          functionLocalDF[!duplicated(functionLocalDF$process, fromLast = T), ]
      }
      

      【讨论】:

        猜你喜欢
        • 2021-06-20
        • 1970-01-01
        • 1970-01-01
        • 2020-08-23
        • 2012-07-09
        • 2020-10-10
        • 1970-01-01
        • 1970-01-01
        • 2020-06-09
        相关资源
        最近更新 更多