多元时间序列的滚动排名?

4

我希望每天对一组变量进行排名(从一个名为zoo的系列开始)。

以下是一个例子:

set.seed(1)
x <- zoo(matrix(rnorm(9), nrow=3), as.Date("2010-01-01") + 0:2)
colnames(x) <- letters[1:3]

我知道的唯一方法是使用rollapply,但这样做会很慢。
>  rollapply(x, 1, rank, by.column=FALSE)
           a b c
2010-01-01 1 3 2
2010-01-02 1 2 3
2010-01-03 1 2 3

有其他建议吗?
2个回答

2

首先,感谢您提供了一个完整可重现的示例。

其次,我喜欢您的解决方案。您可能很难在保持简单的情况下使其更快。一种解决方案是仅处理基础矩阵(而不是zoo对象):

> X <- coredata(x)
> t(apply(X, 1, rank))
     a b c
[1,] 1 3 2
[2,] 1 2 3
[3,] 1 2 3
> 

然后重新附加时间索引。这样可能更快,但不一定更安全或更易于阅读。


谢谢@Dirk!非常好的建议。我猜我的可重复示例在无法复制大型数据集的速度因素方面有限制。但我想这也可以推断出来... - griffin
是的,这就是第二步 -- 创建一些更大的数据和配置文件。如果有低成本的选择,就选择它们。否则,如果你真的需要速度,总还有C/C++。 - Dirk Eddelbuettel
你有关于C++时间序列类的任何建议吗? - griffin
有时,我只是使用 as.numeric(index(x)) 创建浮点数并将其作为单个向量传递。 对于其余部分,例如 coredata(x),我使用矩阵 - 是的,我有点偏爱 Rcpp 和 RcppArmadillo。 也许有一天我会和 Jeff 坐下来商讨如何将一些 xts 索引更接近 Rcpp。 到目前为止,基本的向量和矩阵解决方案运行得很好。 - Dirk Eddelbuettel

2

我认为你的做法是正确的。使用order而不是rank会稍微快一些,但我不明白为什么这样会“非常慢”。也许你可以详细说明一下你实际的问题是什么?

> system.time(for(i in 1:1000) rollapply(z, 1, order, by.column=FALSE))
   user  system elapsed 
      1       0       1 
> system.time(for(i in 1:1000) rollapply(z, 1, rank, by.column=FALSE))
   user  system elapsed 
   1.34    0.00    1.34 

感谢@Joshua!是的,问题在于我正在处理一些非常长而宽的时间序列。这并不意味着这种方法与其他任何方法相比都很慢,只是我在浪费时间,看着它运行,并希望有一个更“向量化”的方法。 - griffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接