在 FUN 中使用 rollapply 宽度参数产生意外结果
Using rollapply width parameter within FUN with unexpected result
我正在使用 rollapply
进行计算,将滚动中的最后一个值除以平均值减一,效果很好,您可以自己尝试:
set.seed(123)
v <- xts(rnorm(5, 5, 1), Sys.Date()-5:1)
rollapplyr(v, width = 3, function(x) x[3, ] / mean(x) - 1)
[,1]
2019-01-12 NA
2019-01-13 NA
2019-01-14 0.24784729
2019-01-15 -0.07241364
2019-01-16 -0.08178780
然后,我还需要 运行 带有另一个参数的函数,例如。 width = 4
。当然,功能也需要调整:
rollapplyr(v, width = 4, function(x) x[4, ] / mean(x) - 1)
[,1]
2019-01-12 NA
2019-01-13 NA
2019-01-14 NA
2019-01-15 -0.02670674
2019-01-16 -0.04696956
为了更灵活,我尝试将width参数直接传入函数中,结果出乎我的意料,虽然第四列是正确的:
rollapplyr(v, width = 4, function(x, width) x[width, ] / mean(x) - 1)
[,1] [,2] [,3] [,4]
2019-01-12 NA NA NA NA
2019-01-13 NA NA NA NA
2019-01-14 NA NA NA NA
2019-01-15 -0.1478253 -0.08442393 0.25895593 -0.02670674
2019-01-16 -0.1137588 0.21861923 -0.05789086 -0.04696956
有人能理解在 FUN 中使用宽度参数在概念上有什么错误吗?如何解释输出?任何人都知道如何正确地做到这一点?
您得到的结果等于此行的结果:
rollapplyr(v, width = 4, function(x) x / mean(x) - 1)
当您只有 1 列时,内部发生的事情是您最终得到下面的代码行和一些已设置的变量。设置变量的结果已经在代码中完成。 rollapply
函数稍微复杂一些。
width <- 4
ind <- as.matrix(seq.int(4, 5))
# FUN passed on from rollappy
FUN <- match.fun(function(x, width) x[width, ] / mean(x) - 1)
sapply(ind, function(i) FUN(.subset_xts(v,
(i - width + 1):i)))
在这些代码行之后是返回的 xts 的构建。
但是一旦你开始调试 sapply
部分发生的事情,(debug FUN)你可以看到 width
没有从 sapply
函数调用传递过来(i) 因此在执行 FUN 时不可用。只有在 rollapply 中定义了宽度的地方,宽度才可用于 .subset 函数。如果您 运行 上面的代码行,也会发生同样的情况。这是定义宽度变量的环境以及执行 FUN 的环境的结果。这些是不同的,这导致你得到的结果。
最好的方法是将 rollapply 包装在另一个函数中,就像您在评论中提到的那样:
function(v,w) {
rollapplyr(v,
width = w,
function(x) x[w, ] / mean(x) - 1)
}
这里 w 是在更高的环境级别上定义的,并在创建 rollapply
中的 FUN 并稍后在 sapply
中执行时正确传递
有关环境的更多信息,您可以在 here 高级 R 书中找到。
我正在使用 rollapply
进行计算,将滚动中的最后一个值除以平均值减一,效果很好,您可以自己尝试:
set.seed(123)
v <- xts(rnorm(5, 5, 1), Sys.Date()-5:1)
rollapplyr(v, width = 3, function(x) x[3, ] / mean(x) - 1)
[,1]
2019-01-12 NA
2019-01-13 NA
2019-01-14 0.24784729
2019-01-15 -0.07241364
2019-01-16 -0.08178780
然后,我还需要 运行 带有另一个参数的函数,例如。 width = 4
。当然,功能也需要调整:
rollapplyr(v, width = 4, function(x) x[4, ] / mean(x) - 1)
[,1]
2019-01-12 NA
2019-01-13 NA
2019-01-14 NA
2019-01-15 -0.02670674
2019-01-16 -0.04696956
为了更灵活,我尝试将width参数直接传入函数中,结果出乎我的意料,虽然第四列是正确的:
rollapplyr(v, width = 4, function(x, width) x[width, ] / mean(x) - 1)
[,1] [,2] [,3] [,4]
2019-01-12 NA NA NA NA
2019-01-13 NA NA NA NA
2019-01-14 NA NA NA NA
2019-01-15 -0.1478253 -0.08442393 0.25895593 -0.02670674
2019-01-16 -0.1137588 0.21861923 -0.05789086 -0.04696956
有人能理解在 FUN 中使用宽度参数在概念上有什么错误吗?如何解释输出?任何人都知道如何正确地做到这一点?
您得到的结果等于此行的结果:
rollapplyr(v, width = 4, function(x) x / mean(x) - 1)
当您只有 1 列时,内部发生的事情是您最终得到下面的代码行和一些已设置的变量。设置变量的结果已经在代码中完成。 rollapply
函数稍微复杂一些。
width <- 4
ind <- as.matrix(seq.int(4, 5))
# FUN passed on from rollappy
FUN <- match.fun(function(x, width) x[width, ] / mean(x) - 1)
sapply(ind, function(i) FUN(.subset_xts(v,
(i - width + 1):i)))
在这些代码行之后是返回的 xts 的构建。
但是一旦你开始调试 sapply
部分发生的事情,(debug FUN)你可以看到 width
没有从 sapply
函数调用传递过来(i) 因此在执行 FUN 时不可用。只有在 rollapply 中定义了宽度的地方,宽度才可用于 .subset 函数。如果您 运行 上面的代码行,也会发生同样的情况。这是定义宽度变量的环境以及执行 FUN 的环境的结果。这些是不同的,这导致你得到的结果。
最好的方法是将 rollapply 包装在另一个函数中,就像您在评论中提到的那样:
function(v,w) {
rollapplyr(v,
width = w,
function(x) x[w, ] / mean(x) - 1)
}
这里 w 是在更高的环境级别上定义的,并在创建 rollapply
中的 FUN 并稍后在 sapply
有关环境的更多信息,您可以在 here 高级 R 书中找到。