Существует несколько простых альтернатив. Очевидно, что вы можете переписать метод в 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
})