【问题标题】:Struggling to understand the behavior of the window<-.ts function in R努力理解 R 中 window<-.ts 函数的行为
【发布时间】:2019-09-13 17:32:42
【问题描述】:

考虑以下创建两个ts 时间序列foo & bar 的代码:

x = 1:22
foo = ts(x, start = 1.5, end = 106.5, frequency = 0.2)
bar = ts(x, start = 2.5, end = 107.5, frequency = 0.2)

foobar 对象是相同的,除了 start 和 end 值:对于 bar,它们都大 1。两者都不是 start /end 值恰好是频率的倍数,但这不应该造成问题。 确实,对于 foobar 都可以成功提取任意大小的窗口:

stats::window(foo, start = 20, end = 30)  # works fine
stats::window(bar, start = 20, end = 30)  # works fine too

但如果我尝试为这些窗口分配值,则只有 foo 有效:

window(foo, start = 20, end = 30) <- NA  # works fine
window(bar, start = 20, end = 30) <- NA  # ERROR!!!

attr(y, "tsp")

window&lt;-.ts 的内部工作基本上调用了 stats::window 函数,所以它应该和显式调用 window() 函数一样工作。


我的理解是,在 ts 的定义中,“开始”和“结束”只是任意单位,例如:秒。所以ts(x, start = 1.5, end = 106.5, frequency = 0.2) 可能意味着:从 1.5 秒开始到 106.5 秒结束的系列,其中每个数字代表 5 秒(1/频率)。 然后,stat::window 函数只选择其起始边界内的值,例如:从 20 到 30 秒。事实上,两个窗口的time() 是相同的,并且似乎证实了这一点:

time(window(foo, start = 20, end = 30))
[1] 21.5 26.5
time(window(bar, start = 20, end = 30))
[1] 22.5 27.5

一个系列从 1.5s 开始,另一个系列从 2.5s 开始这一事实对窗口过程绝对没有影响。然而,当给它赋值时,我的逻辑就崩溃了。

bar中删除一个循环,事情变得更加疯狂:

qux = ts(1:21, start = 2.5, end = 102.5, frequency = 0.2)
window(qux, start = 20, end = 30) <- NA  #ERROR!!

`window

另一个错误!我想我无法理解一些基本概念。 那么我在这里错过了什么?

【问题讨论】:

    标签: r time-series


    【解决方案1】:

    正如你所说,window&lt;-.ts() 在内部使用window() 来创建新对象。它是通过eval.parent() 完成的,其中window() 是用extend=TRUE 调用的,这就是发生错误的时候。因此,我们可以通过考虑以下对来简化我们的分析

    window(foo, start=20, end=30, extend=TRUE)  # works fine
    # Time Series:
    # Start = 20 
    # End = 25 
    # Frequency = 0.2 
    # [1] 5 6
    
    window(bar, start=20, end=30, extend=TRUE)  # error
    # Error in attr(y, "tsp") <- c(ystart, yend, xfreq) : 
    #   invalid time series parameters specified
    

    错误消息中提到的attr(y, "tsp") &lt;- c(ystart, yend, xfreq) 出现在stats:::window.default 的最后。使用的实际值为

    # for foo
    y <- 5:6
    attr(y, "tsp") <- c(20, 25, 0.2)
    
    # for bar
    y <- 5:6
    attr(y, "tsp") <- c(20, 30, 0.2)
    

    25/30 的差异是由于代码中较早的四舍五入造成的,但为什么一个有效,而另一个无效?是频率。小于 1 的频率对我来说似乎有点奇怪。看,如果您将频率设置为 12,f.ex,则每个周期或周期有 12 个样本。也许一个月一次,或者每隔一小时一次,但每 12 个样本应该有一些共同点。如果您将频率设置为 1,您实际上没有周期,您每年采样一次,并且不知道在多年内没有更长的重要周期。频率小于 1 意味着什么?我猜说 0.5 的频率可能意味着每两年进行一次采样,然后每五年进行一次 0.2?也许这是信息,我不知道。

    但是为什么会出错?虽然 25-20 和 30-20 除以 5 都很好,但后一个是一个元素。改用y &lt;- 5:7 就可以了。
    为什么它适用于 foo 而不是 bar?因为四舍五入。
    但为什么呢?可能是因为没有人使用频率小于一的时间序列来测试函数。


    一个可能的解决方法是使用zoo 类时间序列,而不是标准的ts。在这种情况下效果很好,但我没有做过任何其他测试。

    library(zoo)
    
    foo.z <- as.zoo(foo)
    bar.z <- as.zoo(bar)
    
    window(foo.z, start = 20, end = 30) <- NA  # works fine
    window(bar.z, start = 20, end = 30) <- NA  # also works fine
    

    【讨论】:

    • 这是一个很好的答案,谢谢。我有许多生理系列,其中频率以每秒样本数表示是有道理的,即赫兹。我的大部分数据每秒大约有 10 或 100 个样本,但随后,较慢的信号每 5 或 30 秒才采样一次。因此,低于 1 的频率完全有意义,就像 0.5Hz 在信号处理中有意义一样。显然没有解决方案,如果不重写自定义 ts 类,或者在窗口函数中将一个“round()”更改为“floor()”,这可能会在其他地方导致其他不需要的后果.... :-(
    • @Johann:似乎一个解决方案是使用zoo
    • 另一种解决方法是更改​​时间刻度。 Hz 中的秒并不比 RPM 中的分钟更特别。而不是 0.5/秒,你可以有 30/分钟。
    • 也可能是CV的相关讨论:stats.stackexchange.com/questions/120806/…
    • 将时间刻度更改为分钟对于软件包用户来说是非常不自然的,因为它是 base60,而大多数生理信号都是用 base10 频率描述的(例如,每秒 100 个样本将变为每分钟 6000 个样本)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2021-02-23
    • 2011-12-30
    • 2017-02-28
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多