умножение матриц без потери свойств xts - PullRequest
2 голосов
/ 15 февраля 2020

У меня есть xts объект, и я буду sh для создания взвешенных сумм столбцов (и делаю это 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 

1 Ответ

1 голос
/ 15 февраля 2020

Существует несколько простых альтернатив. Очевидно, что вы можете переписать метод в Rcpp, как предложено, но более простой альтернативой является просто перезапись атрибутов после выполнения регулярного умножения матриц.

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

Это не так быстро, как умножение чистой матрицы, но примерно в 10-13 раз быстрее, чем подмножество самого временного ряда.

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 vector')
    x2 <- x %*% z
    att <- attributes(x)
    att$dim <- dim(x2)
    attributes(x2) <- att
    x2
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...