不规则时间序列上的滚动窗口

Posted

技术标签:

【中文标题】不规则时间序列上的滚动窗口【英文标题】:Rolling window over irregular time series 【发布时间】:2012-05-20 08:25:03 【问题描述】:

我有一个使用 xts 的不规则时间序列的事件(帖子),并且我想计算在滚动的每周窗口(或每两周一次或 3 天等)内发生的事件数。数据如下所示:

                    postid
2010-08-04 22:28:07    867
2010-08-04 23:31:12    891
2010-08-04 23:58:05    901
2010-08-05 08:35:50    991
2010-08-05 13:28:02   1085
2010-08-05 14:14:47   1114
2010-08-05 14:21:46   1117
2010-08-05 15:46:24   1151
2010-08-05 16:25:29   1174
2010-08-05 23:19:29   1268
2010-08-06 12:15:42   1384
2010-08-06 15:22:06   1403
2010-08-07 10:25:49   1550
2010-08-07 18:58:16   1596
2010-08-07 21:15:44   1608

应该产生类似的东西

                    nposts
2010-08-05 00:00:00     10
2010-08-06 00:00:00      9
2010-08-07 00:00:00      5

为 2 天的窗口。我从PerformanceAnalytics 等查看了rollapplyapply.rolling 等,它们都假设有规律的时间序列数据。我尝试将所有时间都更改为帖子发生的那一天,并使用ddply 之类的东西每天进行分组,这让我很接近。但是,用户可能不会每天都发帖,所以时间序列仍然是不规则的。我可以用 0 填补空白,但这可能会使我的数据膨胀很多,而且它已经相当大了。

我该怎么办?

【问题讨论】:

xts 包中目前不存在此问题的解决方案,但这个请求已经足够我开始考虑包含一个解决方案。 你有更新@JoshuaUlrich 吗?或者下面答案的效果会用零或 NAs 数据填充缺失的日子,这样我们就可以使用rollapply?我想我可以使用merge... @flodel:这个问题不需要我认为它做了什么(见我的回答)。我以为他们想回顾 n 天在他们原始系列中的每一次观察,这是一个更难解决的问题。 好吧,我不得不承认我没有仔细阅读问题并停在标题处。我确实在寻找更复杂的案例。我的数据不是超级稀疏,所以我将使用merge 使时间序列有规律地间隔。 【参考方案1】:

这是一个使用 xts 的解决方案:

x <- structure(c(867L, 891L, 901L, 991L, 1085L, 1114L, 1117L, 1151L, 
  1174L, 1268L, 1384L, 1403L, 1550L, 1596L, 1608L), .Dim = c(15L, 1L),
  index = structure(c(1280960887, 1280964672, 1280966285, 
  1280997350, 1281014882, 1281017687, 1281018106, 1281023184, 1281025529, 
  1281050369, 1281096942, 1281108126, 1281176749, 1281207496, 1281215744),
  tzone = "", tclass = c("POSIXct", "POSIXt")), class = c("xts", "zoo"),
  .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct", "POSIXt"),
  .indexTZ = "", tzone = "")
# first count the number of observations each day
xd <- apply.daily(x, length)
# now sum the counts over a 2-day rolling window
x2d <- rollapply(xd, 2, sum)
# align times at the end of the period (if you want)
y <- align.time(x2d, n=60*60*24)  # n is in seconds

【讨论】:

【参考方案2】:

这似乎有效:

# n = number of days
n <- 30
# w = window width. In this example, w = 7 days
w <- 7

# I will simulate some data to illustrate the procedure
data <- rep(1:n, rpois(n, 2))

# Tabulate the number of occurences per day:
# (use factor() to be sure to have the days with zero observations included)
date.table <- table(factor(data, levels=1:n))  

mat <- diag(n)
for (i in 2:w)
  dim <- n+i-1
  mat <- mat + diag(dim)[-((n+1):dim),-(1:(i-1))]
  

# And the answer is.... 
roll.mean.7days <- date.table %*% mat

似乎并不太慢(尽管mat 矩阵将获得维度 n*n)。我尝试将 n=30 替换为 n=3000(这会创建一个包含 900 万个元素 = 72 MB 的矩阵),但它在我的计算机上仍然相当快。对于非常大的数据集,先尝试一个子集....使用 Matrix 包 (bandSparse) 中的一些函数来创建mat 矩阵也会更快。

【讨论】:

这是一种将滚动窗口应用于某物的好方法,但如果您没有举例说明如何将其应用于实际时间序列(表示为 POSIXct 日期时间对象,如原始问题),它几乎没有回答问题。 使用不规则间隔的 POSIXct 对象 data &lt;- sample(seq(as.POSIXct("2012/01/01"),as.POSIXct("2012/01/31"),by="hours"), 30) 的向量,您可以将您的 date.table 行替换为:date.table &lt;- table(cut(data,"days")),然后像您一样继续操作,它应该可以解决问题。跨度> plannapus,感谢您对 POSIXct 对象的补充。 任何简单的方法来扩展它不仅可以汇总帖子数量,还可以汇总一个因素 - 例如发帖的作者数量...?【参考方案3】:

使用跑步者可以apply any R function 在滚动窗口上。 OP 需要的是仅在指定时间点计算滚动窗口上的函数(长度)。 使用runner 用户需要指定at 参数来指示应该计算哪些时间点输出。我们可以将时间点向量传递给runner,这是我们在一侧创建的POSIXt 序列。 要使runner 与时间相关,必须按与x 对象对应的日期指定idx。窗口长度可以设置为k = "2 days"

at <- seq(as.POSIXct("2010-08-05 00:00:00"), 
          by = "1 days",
          length.out = 4)

# [1] "2010-08-05 CEST" "2010-08-06 CEST" "2010-08-07 CEST" "2010-08-08 CEST"


runner::runner(
  x = x$postid,
  k = "2 days",
  idx = x$datetime,
  at = at,
  f = length
)
# [1]  3 10  9  5

【讨论】:

以上是关于不规则时间序列上的滚动窗口的主要内容,如果未能解决你的问题,请参考以下文章

R:计算不规则时间序列的滚动和,这些时间序列由 id 变量分组,具有基于时间的窗口

Pandas 时间序列:常规 10 分钟窗口内不规则间隔数据的分组和滚动平均值

R:具有可调节窗口和步长的滚动窗口功能,用于不规则间隔的观察

不规则时间序列上的条件滚动平均值(移动平均值)

熊猫滚动适用于可变窗口长度

Pandas。滚动指定时间窗口和win_type