一个可以用TTR:SMA()
or TTR::EMA()
但这些不允许自定义权重。我想出的一种解决方案是使用data.table::frollapply
:
library(data.table)
x <- data.table(type=rep(1:100, 10000), val=sample(1:1000000, 1000000))
my.roll.2 <- function(x, weights=NULL) {
n <- length(x)
if(is.null(weights)) weights <- 1/(1:n)
sum(weights[1:n]*x, na.rm=T)/sum(weights[1:n])
}
my.roll.1 <- function(x, n, name, ref.col, val.col, weights=NULL) {
x[, (name) := frollapply(get(val.col), n, my.roll.2, weights=weights), by=ref.col]
}
然而性能my.roll.1
不太好(输入数据越大,与其他情况相比,情况会呈指数级恶化):
library(microbenchmark)
library(TTR)
n <- 10
name <- 'test'
microbenchmark(
my.roll=my.roll.1(x, n, name, 'type', 'val')
, frollmean=x[, (name):=data.table::frollmean(val, n), type]
, EMA=x[, (name):=TTR::EMA(val, n), type]
, times=10L
)
Results:
Unit: milliseconds
expr min lq mean median uq max neval
my.roll 7661.0278 7666.0732 7698.69693 7693.28025 7708.6880 7778.6171 10
frollmean 17.1724 17.6321 19.54878 19.56485 20.9490 23.5549 10
EMA 43.0090 43.7332 45.92251 45.79210 47.2391 51.9399 10
data.table::frollmean
速度非常快(用 C 实现),但它不使用任何权重。TTR::EMA
仅使用 EMA 特定权重/平滑(唯一的灵活性是使用参数wilder=TRUE
or wilder=FALSE
)。我的需求是实现的功能my.roll.1
但要更快。