问题描述
我想对需要2个矢量参数的函数进行滚动。这是使用data.table的示例(无效):
library(data.table)
df <- as.data.table(cbind.data.frame(x=1:100,y=101:200))
my_sum <- function(x,y) {
x <- log(x)
y <- x * y
return(x + y)
}
roll_df <- frollapply(df,10,function(x,y) {
my_sum(x,y)})
无法识别y列。 Ofc,解决方案可以使用xts或其他软件包。
编辑: 这是我要应用的真正功能:
library(dpseg)
dpseg_roll <- function(time,price) {
p <- estimateP(x=time,y=price,plot=FALSE)
segs <- dpseg(time,price,jumps=jumps,P=p,type=type,store.matrix=TRUE)
slope_last <- segs$segments$slope[length(segs$segments$slope)]
return(slope_last)
}
解决方法
使用runner,您可以在滚动窗口中应用任何功能。也可以在插入x
参数的data.frame行上创建运行窗口。让我们关注简单的功能my_sum
。运行器中的参数f
只能接受一个对象(在这种情况下为data
)。我建议在对子集应用一些奇特的模型之前,先将browser()
放到该函数中以逐行进行调试(某些算法需要进行最少的观察)。
my_sum <- function(data) {
# browser()
x <- log(data$x)
y <- x * data$y
tail(x + y,1) # return only one value
}
my_sum
应该仅返回一个值,因为runner
为每一行计算-如果my_sum
返回向量,则将获得一个列表。
由于Runner是一个独立的函数,您需要将data.table对象传递给x
。最好的方法是使用x = .SD
(请参阅here为什么)
df[,new_col := runner(
x = .SD,f = my_sum,k = 10
)]
,
我不知道您将如何使用frollapply
(mean
或sum
或其他东西?)。
假设您要使用滚动总和,这可能是一个示例。我重写了您的函数my_sum
,使其直接适用于df
。
my_sum <- function(...) {
v <- c(...)
x <- log(v[[1]])
y <- Reduce(`*`,v)
return(x + y)
}
roll_df <- frollapply(
my_sum(df),10,FUN = sum)
,
如果使用rollapply
,则Zoo中的 coredata=FALSE
会将Zoo对象传递给要应用的功能。 zoo对象由一个时间和一个值部分组成,因此如果x值表示升序值(我将其收集),则可以使用以下内容。请注意,如果两个参数的长度为10,则问题中的my_sum
将返回10元素的结果,因此下面显示的out
是一个100 x 10的Zoo对象,前9行填充了NA。
如果您不希望NA省略fill=NA
,或者您想在开头将函数应用于部分输入而不是fill=NA
,请使用partial=TRUE
。如果只想使用10个元素之一,例如最后一个,请使用function(x) my_sum(time(x),coredata(x))[10]
代替所示的功能,或者只使用out[,10]
。
fortify.zoo(out)
可用于将动物园对象out
转换为数据框(如果您需要这种形式的结果),或者如果您想放下时间,则使用as.data.frame(out)
。 as.data.table(out)
也以类似的方式工作。
library(zoo)
z <- read.zoo(df) # df$x becomes the time part and df$y the value part
out <- rollapplyr(z,function(u) my_sum(time(u),coredata(u)),coredata = FALSE,fill = NA)
dim(out)
## [1] 100 10
请注意,在dpseg_roll
中未定义jumps
和type
。