不规则时间序列的滚动回归

时间:2017-10-21 05:24:08

标签: r iteration linear-regression zoo

摘要(tldr)

我需要对不规则时间序列执行滚动回归(即,间隔可能不是周期性的,并且从0, 1, 2, 3...转到...7, 20, 24, 28...)'简单的数字,并不一定需要日期/时间,但滚动窗口需要是时间。因此,如果我的时间序列被不规则地采样600秒并且窗口是30,则每30秒执行一次回归,并且每30个样本

我已经阅读了一些例子,虽然我可以按时间复制滚动金额和中位数,但我似乎无法弄清楚是否存在回归。

问题

首先,我已经阅读了关于对不规则时间序列数据执行滚动函数的一些其他问题,例如:optimized rolling functions on irregular time series with time-based window,以及:Rolling window over irregular time series

问题在于,到目前为止,提供的示例对于summedian等方程式来说很简单,但我还没有想出如何执行简单的滚动回归,即使用{{ 1}},这仍然是基于同一警告,窗口是基于不规则的时间序列。而且,我的时间序列要简单得多;没有日期是必要的,只是时间过了"。

无论如何,正确的做法对我来说很重要,因为不规则的时间 - 例如,时间间隔中的跳过 - 可能会过度或低估滚动回归中的系数,因为示例窗口将包含额外的时间

所以我想知道是否有人可以帮我创建一个以最简单的方式执行此操作的函数?数据集基于随时间变量测量变量,即2个变量:时间响应。每隔 x 时间经过时间(秒,分钟,因此不是日期/时间格式化)测量时间,但偶尔会变得不规则。

对于函数中的每一行,它应该基于 n 时间单位的宽度执行线性回归。宽度不应超过 n 单位,但可以被覆盖(即减少)以适应不规则的时间采样。因此,例如,如果宽度指定为20秒,但时间每6秒采样一次,则窗口将四舍五入为18,而不是24秒。

我在这里查看了这个问题:How to calculate the average slope within a moving window in R,我在不规则的时间序列中测试了该代码,但它看起来像是基于常规时间序列。

示例数据:

lm

我当前的代码(基于我之前提到的问题)。我知道它没有按时间分组:

sample <- 
structure(list(x = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
29, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 
49), y = c(50, 49, 48, 47, 46, 47, 46, 45, 44, 43, 44, 43, 42, 
41, 40, 41, 40, 39, 38, 37, 38, 37, 36, 35, 34, 35, 34, 33, 32, 
31, 30, 29, 28, 29, 28, 27, 26, 25, 26, 25, 24, 23, 22, 21, 20, 
19)), .Names = c("x", "y"), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -46L))

预期输出(手动计算)如下。输出与常规滚动回归不同 - 一旦时间间隔跳过29(秒),数字就会不同:

library(zoo)
clm <- function(z) coef(lm(y ~ x, as.data.frame(z)))
rollme <- rollapplyr(zoo(sample), 10, clm, by.column = F, fill = NA)

我希望我能提供足够的信息,但是让我知道(或者给我一个好的例子的指南)让我尝试一下?

我尝试过的其他事情: 我已经尝试将时间转换为POSIXct格式,但我不知道如何执行此操作:

    NA
    NA
    NA
    NA
    NA
    NA
    NA
    NA
    NA
    -0.696969697
    -0.6
    -0.551515152
    -0.551515152
    -0.6
    -0.696969697
    -0.6
    -0.551515152
    -0.551515152
    -0.6
    -0.696969697
    -0.6
    -0.551515152
    -0.551515152
    -0.6
    -0.696969697
    -0.6
    -0.551515152
    -0.551515152
    -0.6
    -0.696969697
    -0.605042017
    -0.638888889
    -0.716981132
    -0.597560976
    -0.528301887
    -0.5
    -0.521008403
    -0.642857143
    -0.566666667
    -0.551515152
    -0.551515152
    -0.6
    -0.696969697
    -0.605042017
    -0.638888889
    -0.716981132

更新:添加了tldr部分。

3 个答案:

答案 0 :(得分:1)

试试这个:

# time interval is 1    
sz=10
    pl2=list()
    for ( i in 1:nrow(sample)){
      if (i<sz) period=sz else
      period=length(sample$x[sample$x>(sample$x[i]-sz) & sample$x<=sample$x[i]])-1
      pl2[[i]]=seq(-period,0)
    }

#update for time interval > 1
sz=10
tint=1
pl2=list()
for ( i in 1:nrow(sample)){
  if (i<sz) period=sz else
  period=length(sample$x[sample$x>(sample$x[i]-sz*tint) & sample$x<=sample$x[i]])-1
  pl2[[i]]=seq(-period,0)
}

rollme3 <- rollapplyr(zoo(sample), pl2, clm, by.column = F, fill = NA)

> tail(rollme3)
   (Intercept)          x
41    47.38182 -0.5515152
42    49.20000 -0.6000000
43    53.03030 -0.6969697
44    49.26050 -0.6050420
45    50.72222 -0.6388889
46    54.22642 -0.7169811

答案 1 :(得分:0)

出于完整性考虑,以下是使用 汇总为非等额联接的答案

尽管存在许多类似的问题,例如r calculating rolling average with window based on value (not number of rows or date/time variable),但是当OP正在寻找滚动回归的系数时,这个问题应该自己回答。

library(data.table)
ws <- 10   # size of sliding window in time units
setDT(sample)[.(start = x - ws, end = x), on = .(x > start, x <= end),
              as.list(coef(lm(y ~ x.x))), by = .EACHI]
      x  x (Intercept)        x.x
 1: -10  0    50.00000         NA
 2:  -9  1    50.00000 -1.0000000
 3:  -8  2    50.00000 -1.0000000
 4:  -7  3    50.00000 -1.0000000
 5:  -6  4    50.00000 -1.0000000
 6:  -5  5    49.61905 -0.7142857
 7:  -4  6    49.50000 -0.6428571
 8:  -3  7    49.50000 -0.6428571
 9:  -2  8    49.55556 -0.6666667
10:  -1  9    49.63636 -0.6969697
11:   0 10    49.20000 -0.6000000
12:   1 11    48.88485 -0.5515152
13:   2 12    48.83636 -0.5515152
14:   3 13    49.20000 -0.6000000
15:   4 14    50.12121 -0.6969697
16:   5 15    49.20000 -0.6000000
17:   6 16    48.64242 -0.5515152
18:   7 17    48.59394 -0.5515152
19:   8 18    49.20000 -0.6000000
20:   9 19    50.60606 -0.6969697
21:  10 20    49.20000 -0.6000000
22:  11 21    48.40000 -0.5515152
23:  12 22    48.35152 -0.5515152
24:  13 23    49.20000 -0.6000000
25:  14 24    51.09091 -0.6969697
26:  15 25    49.20000 -0.6000000
27:  16 26    48.15758 -0.5515152
28:  17 27    48.10909 -0.5515152
29:  18 28    49.20000 -0.6000000
30:  19 29    51.57576 -0.6969697
31:  22 32    49.18487 -0.6050420
32:  23 33    50.13889 -0.6388889
33:  24 34    52.47170 -0.7169811
34:  25 35    48.97561 -0.5975610
35:  26 36    46.77358 -0.5283019
36:  27 37    45.75000 -0.5000000
37:  28 38    46.34454 -0.5210084
38:  29 39    50.57143 -0.6428571
39:  30 40    47.95556 -0.5666667
40:  31 41    47.43030 -0.5515152
41:  32 42    47.38182 -0.5515152
42:  33 43    49.20000 -0.6000000
43:  34 44    53.03030 -0.6969697
44:  37 47    49.26050 -0.6050420
45:  38 48    50.72222 -0.6388889
46:  39 49    54.22642 -0.7169811
      x  x (Intercept)        x.x

请注意,时间序列有规律间隔的第10至30行与OP的rollme相同。

as.list()的调用会强制coef(lm(...))的结果显示在单独的列中。


上面的代码使用右对齐的滚动窗口。但是,该代码也可以轻松调整以支持左对齐窗口:

# left aligned window
setDT(sample)[.(start = x, end = x + ws), on = .(x >= start, x < end),
              as.list(coef(lm(y ~ x.x))), by = .EACHI]

答案 2 :(得分:0)

使用runner可以在不规则的时间序列中应用任何R函数。用户必须将放置数据指定为x参数,并将日期向量指定为idx参数(以使Windows与时间相关)。窗口宽度k可以是整数k = 30或类似seq.POSIXt k = "30 secs"中的字符。

  1. 第一个示例显示了如何从lm函数获取两个参数-输出将为矩阵
library(runner)

runner(
  x = sample,
  k = "30 secs",
  idx = sample$datetime,
  function(x) {
    coefficients(lm(y ~ x, data = x))
  }
)
  1. 或者可以为每个参数分别执行runner
library(runner)

sample$intercept <- runner(
  sample,
  k = "30 secs",
  idx = sample$datetime,
  function(x) {
    coefficients(lm(y ~ x, data = x))[1]
  }
)

sample$slope <- runner(
  sample,
  k = "30 secs",
  idx = sample$datetime,
  function(x) {
    coefficients(lm(y ~ x, data = x))[2]
  }
)
head(sample, 15)

#               datetime  x  y intercept      slope
# 1  2020-04-13 09:27:20  0 50  50.00000         NA
# 2  2020-04-13 09:27:21  1 49  50.00000 -1.0000000
# 3  2020-04-13 09:27:25  2 48  50.00000 -1.0000000
# 4  2020-04-13 09:27:29  3 47  50.00000 -1.0000000
# 5  2020-04-13 09:27:29  4 46  50.00000 -1.0000000
# 6  2020-04-13 09:27:32  5 47  49.61905 -0.7142857
# 7  2020-04-13 09:27:34  6 46  49.50000 -0.6428571
# 8  2020-04-13 09:27:38  7 45  49.50000 -0.6428571
# 9  2020-04-13 09:27:38  8 44  49.55556 -0.6666667
# 10 2020-04-13 09:27:41  9 43  49.63636 -0.6969697
# 11 2020-04-13 09:27:44 10 44  49.45455 -0.6363636
# 12 2020-04-13 09:27:47 11 43  49.38462 -0.6153846
# 13 2020-04-13 09:27:48 12 42  49.38462 -0.6153846
# 14 2020-04-13 09:27:49 13 41  49.42857 -0.6263736
# 15 2020-04-13 09:27:50 14 40  49.34066 -0.6263736

带有日期时间列的数据

sample <- structure(
  list(
    datetime = c(3, 1, 4, 4, 0, 3, 2, 4, 0, 3, 3, 3, 1, 1, 1, 3, 0, 2, 4, 2, 2, 
                 3, 0, 1, 2, 4, 0, 1, 4, 4, 1, 2, 1, 3, 0, 4, 4, 1, 3, 0, 0, 2, 
                 1, 0, 2, 0) + Sys.time(),
    x = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 
          20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 
          39, 40, 41, 42, 43, 44, 47, 48, 49), 
    y = c(50, 49, 48, 47, 46, 47, 46, 45, 44, 43, 44, 43, 42, 41, 40, 41, 40, 39,
          38, 37, 38, 37, 36, 35, 34, 35, 34, 33, 32, 31, 30, 29, 28, 29, 28, 27, 
          26, 25, 26, 25, 24, 23, 22, 21, 20,19)
  ), 
  .Names = c("x", "y"), 
  class = c("tbl_df", "tbl", "data.frame"), 
  row.names = c(NA, -46L)
)