15

我正在尝试为不规则的时间序列数据集提取有趣的统计数据,但未能找到适合该工作的工具。很容易找到用于处理任何时间定期采样的时间序列或基于索引的序列的工具,尽管我对我试图解决的问题不太幸运。

首先,一个可重现的数据集:

library(zoo)
set.seed(0)
nSamples    <- 5000
vecDT       <- rexp(nSamples, 3)
vecTimes    <- cumsum(c(0,vecDT))
vecDrift    <- c(0, rnorm(nSamples, mean = 1/nSamples, sd = 0.01))
vecVals     <- cumsum(vecDrift)
vecZ        <- zoo(vecVals, order.by = vecTimes)
rm(vecDT, vecDrift)

假设时间以秒为单位。该系列有近 1700 秒(仅 30 分钟),在此vecZ期间有 5001 个条目。(注意:我会尝试使用xts,但xts似乎需要日期信息,并且我宁愿在不相关时不使用特定日期。)

我的目标如下:

  • 确定每个点之前 3 分钟和之后 3 分钟的值的索引。由于时间是连续的,我怀疑任何两点之间恰好相隔 3 分钟。我想找到的是给定点之前最多 3 分钟和至少 3 分钟之后的点,即类似于以下内容(在伪代码中):

    backIX(t, vecZ, tDelta) = min{ix in length(vecZ) : t - time(ix) < tDelta} forwardIX(t, vecZ, tDelta) = min{ix in length(vecZ) : time(ix) - t > tDelta}

    所以,3 分钟,tDelta = 180. 如果t=2500,则结果为forwardIX()3012(即 time(vecZ)[2500] 为 860.1462,而 time(vecZ)[3012] 为 1040.403,或刚刚超过 180 秒后),输出为backwardIX()2020(对应于时间 680.7162 秒)。

    理想情况下,我想使用不需要的函数t,因为这将需要length(vecZ)调用该函数,这忽略了可以更有效地计算滑动时间窗口的事实。

  • 将函数应用于滚动时间窗口中的所有值。我见过rollapply,它采用固定的窗口大小(即固定数量的索引,但不是固定的时间窗口)。我可以用一个简单的方法来解决这个问题,使用foreach按索引计算的循环(或;-))t,但我想知道是否已经实现了一些简单的函数,例如计算给定时间范围内所有值的平均值的函数. 由于这可以通过在窗口上滑动的简单汇总统计信息有效地完成,因此它的计算成本应该低于多次访问所有数据以计算每个统计信息的函数。一些相当自然的函数:均值、最小值、最大值和中值。

    即使窗口不随时间变化,改变窗口大小的能力也足够了,我可以使用上述问题的结果找到窗口大小。但是,这似乎仍然需要额外的计算,因此能够指定基于时间的间隔似乎更有效。

R 中是否有有助于在时间窗口中对数据进行此类操作的包,还是我不走运,我应该编写自己的函数?


注意 1:这个问题试图做类似的事情,除了不相交的时间间隔,而不是滚动的时间窗口,例如,我可以调整这个来对每个连续的 3 分钟块进行分析,但我看不到调整这个的方法滚动 3 分钟间隔。

注意 2:我发现从zoo对象切换到数字向量(对于时代而言)显着加快了第一个目标的范围查找/窗口端点识别问题。这仍然是一种幼稚的算法,但值得一提的是,使用zoo对象可能不是幼稚方法的最佳选择。

4

2 回答 2

1

Here's what I was suggeting, but I'm not sure it exactly answers your question

#Picking up where your code left off
library(xts)
library(TTR)
x <- .xts(vecZ, vecTimes)
xx <- na.locf(cbind(xts(, seq.POSIXt(from=start(x), to=end(x), by='sec')), x))
x$means <- runMean(xx, n=180)
out <- x[!is.na(x[, 1]), ]
tail(out)

                                  x     means
1969-12-31 18:28:17.376141 0.2053531 0.1325938
1969-12-31 18:28:17.379140 0.2101565 0.1329065
1969-12-31 18:28:17.619840 0.2139770 0.1332403
1969-12-31 18:28:17.762765 0.2072574 0.1335843
1969-12-31 18:28:17.866473 0.2065790 0.1339608
1969-12-31 18:28:17.924270 0.2114755 0.1344264
于 2012-05-05T22:43:43.210 回答
1

从 v1.9.8 版本开始(CRAN 2016 年 11 月 25 日),在非等值连接中聚合的能力,可用于在不规则时间序列的滑动时间窗口上应用滚动函数。

为了演示和验证,使用了较小的数据集。

library(data.table)   # development version 1.11.9 used

# create small dataset
set.seed(0)
nSamples    <- 10
vecDT       <- rexp(nSamples, 3)
vecTimes    <- cumsum(c(0,vecDT))
vecVals     <- 0:nSamples
vec         <- data.table(vecTimes, vecVals)
vec
      vecTimes vecVals
 1: 0.00000000       0
 2: 0.06134553       1
 3: 0.10991444       2
 4: 0.15651286       3
 5: 0.30186907       4
 6: 1.26685858       5
 7: 1.67671260       6
 8: 1.85660688       7
 9: 2.17546271       8
10: 2.22447804       9
11: 2.68805641      10
# define window size in seconds 
win_sec = 0.3

# aggregate in sliding window by a non-equi join
vec[.(t = vecTimes, upper = vecTimes + win_sec, lower = vecTimes - win_sec), 
    on = .(vecTimes < upper, vecTimes > lower), 
    .(t, .N, sliding_mean = mean(vecVals)), by = .EACHI]
     vecTimes     vecTimes          t N sliding_mean
 1: 0.3000000 -0.300000000 0.00000000 4          1.5
 2: 0.3613455 -0.238654473 0.06134553 5          2.0
 3: 0.4099144 -0.190085564 0.10991444 5          2.0
 4: 0.4565129 -0.143487143 0.15651286 5          2.0
 5: 0.6018691  0.001869065 0.30186907 4          2.5
 6: 1.5668586  0.966858578 1.26685858 1          5.0
 7: 1.9767126  1.376712596 1.67671260 2          6.5
 8: 2.1566069  1.556606875 1.85660688 2          6.5
 9: 2.4754627  1.875462707 2.17546271 2          8.5
10: 2.5244780  1.924478037 2.22447804 2          8.5
11: 2.9880564  2.388056413 2.68805641 1         10.0

前两列分别显示了时间间隔的上限和下限,分别t是原始vecTimes,并N表示计算滑动平均值时包含的数据点的数量。

于 2018-12-28T09:05:50.603 回答