说我在R中有以下ts对象。
x <- ts(data = matrix(1:10, 5, 2), start = 1/12, deltat = 1/12)
现在我想对这个时间序列的每个条目应用函数f:函数f取决于时间序列的值和相应的时间,例如:
f <- function(z, time){z*time}
我正在寻找一种有效的方法来实现这一点:到目前为止,我只针对这样的解决方案进行了一些工作:
timex <- seq(from = 1/12, by = 1/12, length = 5)
apply(x, 2, function(y){ apply(cbind(y, timex),1, function(z) f(z[1], z[2]))})
此解决方案提供了正确的结果,但我确信有更直接的方法。
我正在寻找一种适用于更多&#34;复杂功能的方法&#34; f:特别是如果长度(x)> 1,则无法直接调用f(x,time(x))。
对我来说,时间序列是ts格式并不重要,所以如果有一个不同时间序列格式的解决方案,我全都赞成它。对我来说最重要的是表现。 最后的结果也不一定是时间序列对象。
你们有任何提示吗? 谢谢。
修改 问题似乎是x一旦使用了应用就失去了它的ts属性。 特别是不能再使用 time 命令。
apply(x, 2, class)
Series 1 Series 2
"integer" "integer"
class(x)
[1] "mts" "ts" "matrix"
编辑2: 我被要求提供一个更复杂的函数f的例子: 这是一个计算某些金融产品价值的函数。
f <- function(s0, t){
option.times <- 1:20/2
tau <- option.times[option.times >= t] - t
d = (log(1.5/s0) - 0.0098*tau)/(0.0098* sqrt(tau))
p1 <- pnorm(d)
p2 <- s0 / 1.5* exp((1/2*0.02^2 + 0.0098)*tau) * pnorm(d-0.02*sqrt(tau))
sum((p1-p2)*exp(-0.02*tau))*100
}
我无法提供我正在使用的时间序列:但它是一个530x10000时间序列,每周数据(时间(x)从0开始,以deltat = 1/52进行)。 对于这个函数f和我的时间序列,我得到了
> system.time(apply(x, 2, function(y){ apply(cbind(y, timex),1, function(z) f(z[1], z[2]))}))
User System verstrichen
69.62 0.03 69.75
> system.time(mapply(f, x, time(x)))
User System verstrichen
79.01 0.06 79.12
所以mapply比使用apply两次稍慢。
答案 0 :(得分:1)
您可以使用mapply
将多个向量用作输入:
x <- ts(data = matrix(1:10, 5, 2), start = 1/12, deltat = 1/12)
f <- function(z, time){z*time}
mapply(f, x, time(x))
#> [1] 0.08333333 0.33333333 0.75000000 1.33333333 2.08333333 0.50000000
#> [7] 1.16666667 2.00000000 3.00000000 4.16666667
修改强> 我可以用真实的功能和实际的数据重现你的时间:
n <- 530
m <- 10000
x <- ts(data = matrix(rlnorm(n * m), n, m), start = 0, deltat = 1/52)
f <- function(s0, t){
option.times <- 1:20/2
tau <- option.times[option.times >= t] - t
d = (log(1.5/s0) - 0.0098*tau)/(0.0098* sqrt(tau))
p1 <- pnorm(d)
p2 <- s0 / 1.5* exp((1/2*0.02^2 + 0.0098)*tau) * pnorm(d-0.02*sqrt(tau))
sum((p1-p2)*exp(-0.02*tau))*100
}
timex <- time(x)
system.time(r1 <- apply(x, 2, function(y){ apply(cbind(y, timex),1, function(z) f(z[1], z[2]))}))
#> User System verstrichen
#> 67.002 0.059 67.089
system.time(r2 <- matrix(mapply(f, x, time(x)), n, m))
#> User System verstrichen
#> 78.975 0.244 79.250
all(r1 == r2)
#> [1] TRUE
但是,你的函数允许至少部分向量化,这样就足以在所有行上进行(显式)循环而不是所有矩阵元素的(隐式)循环:
g <- function(s0, t){
option.times <- 1:20/2
tau <- option.times[option.times >= t] - t
d = outer(-0.0098*tau, log(1.5/s0), FUN = "+")/(0.0098 * sqrt(tau))
p1 <- pnorm(d)
p2 <- outer(exp((1/2*0.02^2 + 0.0098)*tau), s0 / 1.5, FUN = "*") * pnorm(d - 0.02*sqrt(tau))
colSums((p1 - p2)*exp(-0.02*tau))*100
}
r3 <- matrix(0, n ,m)
timex <- time(x)
system.time(for (i in seq_along(timex)) {
r3[i, ] <- g(x[i, ], timex[i])
})
#> User System verstrichen
#> 4.955 0.136 4.919
all(r3 == r2)
#> [1] TRUE
可能有办法完全矢量化函数......