【问题标题】:Moving variance in RR中的移动方差
【发布时间】:2020-01-28 02:10:31
【问题描述】:

我知道 R 中的 filter() 函数计算移动平均线。我想知道是否存在返回移动方差或标准偏差的函数,以便将其与filter() 函数的输出并排显示在图中。

【问题讨论】:

    标签: r


    【解决方案1】:

    考虑 zoo 包。例如filter() 给出:

    > filter(1:100, rep(1/3,3))
    Time Series:
    Start = 1 
    End = 100 
    Frequency = 1 
      [1] NA  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
     [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
     [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
     [76] 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 NA
    

    动物园 中的rollmean() 给出:

    > rollmean(1:100, k = 3, na.pad = TRUE)
      [1] NA  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
     [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
     [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
     [76] 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 NA
    

    这是相同的(在本例中为 3 点移动平均线)。

    虽然 zoo 没有 rollsd()rollvar(),但它确实有 rollapply(),其工作方式与 apply() 函数类似,可将任何 R 函数应用于指定窗口。

    > rollapply(1:100, width = 3, FUN = sd, na.pad = TRUE)
      [1] NA  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
     [26]  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
     [51]  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
     [76]  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 NA
    Warning message:
    In rollapply.zoo(zoo(data), ...) : na.pad argument is deprecated
    

    或者更有趣的事情:

    > rollapply(vec, width = 3, FUN = sd, na.pad = TRUE)
      [1]        NA 0.3655067 0.8472871 0.5660495 0.3491970 0.4732417 0.9236859
      [8] 0.8075226 1.8725851 1.1930784 0.6329325 1.1412416 0.8430772 0.5808005
     [15] 0.3838545 1.1738170 1.1655400 1.3241700 0.6876834 0.1534157 0.4858477
     [22] 0.9843506 0.6002713 0.6897541 2.0619563 2.5675788 6.3522039 6.0066864
     [29] 6.2618432 5.1704866 2.1360853 2.5602557 1.0408528 1.0316396 4.9441628
     [36] 5.0319314 5.7589716 3.2425000 4.8788158 2.0847286 4.5199291 2.5323486
     [43] 2.1987149 1.8393000 1.2278639 1.5998965 1.5341485 4.4287108 4.4159166
     [50] 4.3224546 3.6959067 4.9826264 5.3134044 8.4084322 9.1249234 7.5506725
     [57] 3.8499136 3.9680487 5.6362296 4.9124095 4.3452706 4.0227141 4.5867559
     [64] 4.7350394 4.3203807 4.4506799 7.2759499 7.6536424 7.8487654 2.0905576
     [71] 4.0056880 5.6209853 1.5551659 1.3615268 2.8469458 2.8323588 1.9848578
     [78] 1.1201124 1.4248380 1.7802571 1.4281773 2.5481935 1.8554451 1.0925410
     [85] 2.1823722 2.2788755 2.4205378 2.0733741 0.7462248 1.3873578 1.4265948
     [92] 0.7212619 0.7425993 1.0696432 2.4520585 3.0555819 3.1000885 1.0945292
     [99] 0.3726928        NA
    Warning message:
    In rollapply.zoo(zoo(data), ...) : na.pad argument is deprecated
    

    您可以通过使用fill = NA 参数来消除警告,如

    > rollapply(vec, width = 3, FUN = sd, fill = NA)
    

    【讨论】:

    • 谢谢 Gavin,我想这是一个附加问题,但您知道使用 ts 的基本 R 解决方案吗?
    • @Zhubarb 不,不是一个函数。您可以从基本 R 部分中编写代码(就像 rollapply() 一样),但没有任何罐头我知道
    【解决方案2】:

    TTR 包有 runSD 等:

    > library(TTR)
    > ls("package:TTR", pattern="run*")
     [1] "runCor"    "runCov"    "runMAD"    "runMax"    "runMean"  
     [6] "runMedian" "runMin"    "runSD"     "runSum"    "runVar"
    

    runSD 将比rollapply 快得多,因为它避免了许多 R 函数调用。例如:

    rzoo <- function(x,n) rollapplyr(x, n, sd, fill=NA)
    rttr <- function(x,n) runSD(x, n)
    library(rbenchmark)
    set.seed(21)
    x <- rnorm(1e4)
    all.equal(rzoo(x,250), rttr(x,250))
    # [1] TRUE
    benchmark(rzoo(x,250), rttr(x,250))[,1:6]
    #           test replications elapsed relative user.self sys.self
    # 2 rttr(x, 250)          100    0.58    1.000      0.58     0.00
    # 1 rzoo(x, 250)          100   54.53   94.017     53.85     0.06
    

    【讨论】:

    • 不错的包,谢谢!对于其他用户,如果您提供长度为 &lt;n 的向量,则此函数会产生错误,这意味着如果您将其应用于数据集中的许多组(例如,不同的股票,使用 data.table),以及其中任何一个数据太少,整个操作会产生is outside valid range:...类型的错误。当提供的数据太少时,用户可以通过包装函数来提供不同的行为(如返回NAs)来解决这个问题。
    • @MichaelOhlrogge:感谢您的评论!我喜欢在提供的数据太少时返回所有 NA 的想法。我会考虑如何在 TTR 函数中直接实现类似的东西(参见#68)。
    • zoo 确实有几个函数可以硬编码 FUN 参数以获得速度。这运行时间不到 rttr roll &lt;- function(x, n) sqrt(n * (rollmeanr(x*x, n, fill = NA) - rollmeanr(x, 250, fill = NA)^2)/(n - 1)) 的一半
    • @G.Grothendieck:这是一个很好的观点。如果我特例 x 和 y 是同一个对象,TTR 函数会快很多。
    【解决方案3】:

    zoo 包中的rollapply 采用任意函数。它与filter 的不同之处在于它默认排除了NAs。

    话虽如此,但为一个很容易自己滚动的函数加载一个包并没有多大意义(双关语)。

    这是右对齐的:

    my.rollapply <- function(vec, width, FUN) 
        sapply(seq_along(vec), 
               function(i) if (i < width) NA else FUN(vec[i:(i-width+1)]))
    
    set.seed(1)
    vec <- sample(1:50, 50)
    my.rollapply(vec, 3, sd)
     [1]        NA        NA  7.094599 12.124356 16.522712 18.502252 18.193405  7.234178  8.144528
    [10] 14.468356 12.489996  3.055050 20.808652 19.467922 18.009257 18.248288 15.695010  7.505553
    [19] 10.066446 11.846237 17.156146  6.557439  5.291503 23.629078 22.590558 21.197484 22.810816
    [28] 24.433583 19.502137 16.165808 11.503623 12.288206  9.539392 13.051181 13.527749 19.974984
    [37] 19.756855 17.616280 19.347696 18.248288 15.176737  6.082763 10.000000 10.016653  4.509250
    [46]  2.645751  1.527525  5.291503 10.598742  6.557439
    
    # rollapply output for comparison
    rollapply(vec, width=3, sd, fill=NA, align='right')
     [1]        NA        NA  7.094599 12.124356 16.522712 18.502252 18.193405  7.234178  8.144528
    [10] 14.468356 12.489996  3.055050 20.808652 19.467922 18.009257 18.248288 15.695010  7.505553
    [19] 10.066446 11.846237 17.156146  6.557439  5.291503 23.629078 22.590558 21.197484 22.810816
    [28] 24.433583 19.502137 16.165808 11.503623 12.288206  9.539392 13.051181 13.527749 19.974984
    [37] 19.756855 17.616280 19.347696 18.248288 15.176737  6.082763 10.000000 10.016653  4.509250
    [46]  2.645751  1.527525  5.291503 10.598742  6.557439
    

    【讨论】:

    • 不错的解决方案。它比rollapplyr 快一点。出于某种原因,在sd 中,大约 500 条数据中存在一点差异:1e-14。为什么应该存在舍入(?)问题?
    • my.rollapply=function(vec, width,FUN) return(c(rep(NA,width-1),sapply(seq_along(vec[width:length(vec)]), function(i) FUN(vec[i:(i+width-1)])))) 应该快一点:更少的重复,更少的指令
    【解决方案4】:

    runner 包中的runner 函数在运行的窗口上应用任何 R 函数。使用runner 可以通过设置长度klag 来指定简单窗口。按照 OOP 在 4 元素窗口上的建议,在移动 sd 下方。

    library(runner)
    
    set.seed(1)
    x <- rnorm(20, sd = 1)
    runner(x, sd, k = 4, na_pad = TRUE)
    
    #[1]        NA        NA        NA 1.1021597 0.9967429 1.1556947 0.9884053 0.6902835 0.7180483 0.4647160
    #[11] 0.7454670 0.7489618 0.9449882 1.5821988 1.4459037 1.3889432 1.3954101 0.6193867 0.5296744 0.4266423
    

    要在日期窗口上应用运行函数,应指定idxidx 的长度应与x 的长度相同,并且应为日期或整数类型。下面的示例说明了大小为 k = 4 的窗口落后于 lag = 1。括号中为每个窗口的索引范围。

    idx <- c(4, 6, 7, 13, 17, 18, 18, 21, 27, 31, 37, 42, 44, 47, 48)
    runner::runner(x = 1:15, 
                   k = 5,
                   lag = 1,
                   idx = idx,
                   f = function(x) mean(x))
    
    # [1]   NA  1.0  1.5   NA  4.0  4.5  4.5  6.0   NA  9.0   NA 11.0 12.0 12.5 13.5
    

    更多信息documentation and vignettes

    【讨论】:

      猜你喜欢
      • 2018-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多