【问题标题】:Use rollapply with xts object and an anonymous defined function将 rollapply 与 xts 对象和匿名定义函数一起使用
【发布时间】:2019-05-12 00:47:42
【问题描述】:

我正在尝试在向下滑动 xts 数据框的列的窗口上使用 rollapply 创建滚动计算。例如,假设我定义了一个 xts 对象:

df1 <- data.frame(A = c(1,2,3,4,5,6,7,8,9),
              B = c(3,4,5,6,7,8,9,10,11))
dfxts <- xts(df1, order.by = as.Date(c(30,31,32,33,34,35,36,37,38)))

这给出了 xts 函数:

           A  B
1970-01-31 1  3
1970-02-01 2  4
1970-02-02 3  5
1970-02-03 4  6
1970-02-04 5  7
1970-02-05 6  8
1970-02-06 7  9
1970-02-07 8 10
1970-02-08 9 11

据我了解宽度参数,它定义了发生某些操作的滑动窗口的长度,例如,平均操作(虽然我不清楚“宽度”)。

假设我想在宽度为 3 的窗口上创建滚动操作,在每个位置添加窗口的第 2 和第 3 个元素。在窗口的每个位置,我想添加 x(2) + x(3)。我会得到:

           A  B
1970-01-31 NA NA
1970-02-01 NA NA
1970-02-02 5  9
1970-02-03 7  11
1970-02-04 9  13
1970-02-05 11 15
1970-02-06 13 17
1970-02-07 15 19
1970-02-08 17 21

我尝试通过以下方式实现:

 rollapply(dfxts, width = 3, FUN=function(x) x(2)+x(3), align = "right")

我得到了错误:

“总结时出错:找不到函数“x”

我想我误解了如何使用 rollapply,如何实现匿名函数,或两者兼而有之。

【问题讨论】:

    标签: r apply


    【解决方案1】:

    我不确定您是否可以将rollapply 应用于整个数据框。您可以使用lapply 将其分别应用于每一列,并且由于您想要第二个和第三个元素的sum,您可以将width 减少为2

    library(zoo)
    lapply(dfxts, function(x) rollapply(x, width = 2, FUN=sum))
    
    
    #$A
    #            A
    #1970-01-31 NA
    #1970-02-01  3
    #1970-02-02  5
    #1970-02-03  7
    #1970-02-04  9
    #1970-02-05 11
    #1970-02-06 13
    #1970-02-07 15
    #1970-02-08 17
    
    #$B
    #            B
    #1970-01-31 NA
    #1970-02-01  7
    #1970-02-02  9
    #1970-02-03 11
    #1970-02-04 13
    #1970-02-05 15
    #1970-02-06 17
    #1970-02-07 19
    #1970-02-08 21
    

    如果由于某种原因您必须将 width 保留为 3 并且无法更改它,那么我们可以这样做

    lapply(dfxts, function(x) rollapply(x, width = 3, FUN=function(y) sum(y[2],y[3])))
    

    这将给出相同的输出,除了前两个值将是 NA 而不是一个。


    编辑

    正如 cmets 中所提到的,实际应用的函数比提供的函数更复杂,它需要使用自定义函数而不是内置函数,我们可以使用 coredata 获取实际数据然后应用我们的功能相应。

    所以在给定的例子中,我们可以这样做

    rollapply(dfxts, width = 3, FUN=function(x) coredata(x[2]) +  coredata(x[3]))
    

    但是,对于更通用的方法,我们可以只调用一次coredata,然后按照我们想要的方式使用它们。所以如果我们想申请操作5*x(5) - 8*x(7) + x(15),我们可以这样做

    rollapply(dfxts, width = 15, FUN=function(x) {
              vals <- coredata(x)
              5*vals[5] - 8*vals[7] + vals[15]
    })
    

    【讨论】:

    • 谢谢。我提出的问题的很好的解决方案,但我选择了 x(2) + x(3) 的一个糟糕的例子。我真正的问题是对宽度内的值进行更复杂的操作。例如,我的宽度可能是 15,而我的实际函数可能看起来更像 5*x(5) - 8*x(7) + x(15)。所以,我需要调用自己定义的函数,而不是使用像“sum”这样的内置函数。
    • @Ernie 我已经更新了我的答案。看看有没有帮助谢谢:)
    • 完美!不使用“coredata”进行转换是我的主要错误。
    【解决方案2】:

    只需对您的 rollapply 稍作更改(sum(x[2],x[3]) 而不是 x(2)+x(3))就可以了:

    rollapply(dfxts, width = 3, FUN=function(x) sum(x[2],x[3]), align = "right")
    

    这是我得到的输出:

    #            A  B
    #1970-01-31 NA NA
    #1970-02-01 NA NA
    #1970-02-02  5  9
    #1970-02-03  7 11
    #1970-02-04  9 13
    #1970-02-05 11 15
    #1970-02-06 13 17
    #1970-02-07 15 19
    #1970-02-08 17 21
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 2015-08-23
      相关资源
      最近更新 更多