矩阵乘法而不丢失xts属性

问题描述 投票:1回答:1

我有一个xts对象,我希望创建各列的加权总和(并执行LOT)。到目前为止,最简单的方法是矩阵乘法,但是结果失去了很好的xts质量。

通过创建一个新的xts对象很容易将它们添加回去,但是它既缓慢又乏味。

例如:

dd <- xts(matrix(rnorm(200), ncol=2), Sys.Date() + 1:100)
w_sum <- dd %*% c(-1, 1)

...,问题是:

> tail(w_sum)
             [,1]
 [95,]  0.1758262
 [96,] -0.3310975
 [97,] -0.1204836
 [98,] -1.2242001
 [99,] -1.7333222
[100,]  1.1216603

解决方法是:

w_sumx <- xts(dd %*% c(-1, 1), index(dd))

但是不仅麻烦,而且很慢。另外,我感兴趣地注意到xts减法的速度非常快。有没有一种方法可以利用xts的快速内部功能?

f1 <- function() xts(dd %*% c(-1, 1), index(dd))
f2 <- function() dd[,2] - dd[,1]

> microbenchmark::microbenchmark(f1(), f2(), times = 1000)
Unit: microseconds
 expr  min   lq     mean median     uq    max neval cld
 f1() 83.7 97.3 114.1294 104.65 115.00 6688.4  1000   b
 f2() 26.3 34.0  40.6202  38.85  45.15  155.4  1000  a 
r xts
1个回答
0
投票

存在一些简单的替代方法。显然,您可以按照建议在Rcpp中重写该方法,但是更简单的选择是在执行矩阵正则乘法之后覆盖属性。

dd_new <- dd %*% c(-1, 1)
att <- attributes(dd)
att$dim <- dim(dd_new)
attributes(dd_new) <- att

这不像纯矩阵乘法那样快,但是比对时间序列本身进行子集化要快。

microbenchmark::microbenchmark(xts = dd[, 1] - dd[, 2], 
                               matmult = dd %*% c(1, -1),
                               xtsmatmult = xts(dd %*% c(1, -1), index(dd)),
                               "%.%" = dd %.% c(1, -1),
                               "%-%" = dd %-% c(1, -1),
                               times = 1e5)
Unit: milliseconds
       expr    min     lq    mean median     uq    max neval
        xts 0.0396 0.0685 0.11200 0.0998 0.1170  15.40 1e+05
    matmult 0.0008 0.0021 0.00352 0.0028 0.0040   7.71 1e+05
 xtsmatmult 0.0853 0.1380 0.22900 0.2100 0.2300 117.00 1e+05
        %.% 0.0025 0.0055 0.00905 0.0076 0.0099   8.97 1e+05
        %-% 0.0096 0.0183 0.03030 0.0268 0.0318 101.00 1e+05

在上面,%.%是一个准系统函数,仅保留矩阵乘法并覆盖属性,而%-%添加一些简单的输入检查,以确保尺寸可接受,并使用S3类样式为了简化概括。

功能:

请注意,compiler::cmpfun函数已用于模拟包函数。在这种情况下,效果不明显。

`%.%` <- compiler::cmpfun(function(x, z){
    x2 <- x %*% z
    att <- attributes(x)
    att$dim <- dim(x2)
    attributes(x2) <- att
    x2
})
`%-%` <- function(x, z)
    UseMethod('%-%')
`%-%.xts` <- compiler::cmpfun(function(x, z){
    ## 
    if(!is.xts(x))
        stop('x must be an xts object')
    if(!is.numeric(z) || !(n <- length(z)) == ncol(x) || n == 0)
        stop('z must be an index ector')
    x2 <- x %*% z
    att <- attributes(x)
    att$dim <- dim(x2)
    attributes(x2) <- att
    x2
})
© www.soinside.com 2019 - 2024. All rights reserved.