R-滚动平均/标准偏差与条件



我有一个问题,要根据条件计算滚动平均值/标准偏差。老实说,这更像是一个语法问题,但是由于我认为它正在放慢我的代码,因此我认为我应该在这里要求它找出正在发生的事情。我有一些带有Stock NameMidquotes等列的财务数据,并且我想根据股票计算滚动平均值和滚动标准偏差。

现在,我希望计算每个股票的波动性,这是通过获取前20个中标的滚动标准偏差来完成的。为此,在搜索stackoverflow论坛后,我使用data.table软件包找到了一条线,如下所示:

DT[, volatility:=( roll_sd(DT$Midquotes, 20, fill=0, align = "right") ), by = Stock]

其中DT是包含我所有数据的data.table

现在,这在计算上很慢,尤其是当我将其与典型的滚动标准偏差计算进行比较时,没有任何条件:

DT$volatility <- roll_sd(DT$Midquotes, 20, fill=0, align = "right")

但是,当我尝试使用条件的滚动标准偏差进行类似的事情时,R不会让我这样做:

DT$volatility <- DT[, ( roll_sd(DT$Midquotes, 20, fill=0, align = "right") ), by = Stock]

此行提出了一个错误:

Error: cannot allocate vector of size 10.9 Gb

所以我只是想知道,为什么这一行:DT[, volatility:=( roll_sd(DT$Midquotes, 20, fill=0, align = "right") ), by = Stock]这么慢?每次为每个不同股票计算滚动标准偏差时,是否也可能制作整个data.table的副本?

我认为您的问题是您对:=函数的使用,并且在方括号内使用DT。我认为您的设置就像:

> library(data.table)
> set.seed(83385668)
> DT <- data.table(
+   x     = rnorm(5 * 3), 
+   stock = c(sapply(letters[1:3], rep, times = 5)),
+   time  = c(replicate(3, 1:5)))
> DT
              x stock time
 1:  0.25073356     a    1
 2: -0.24408170     a    2
 3: -0.87475856     a    3
 4:  0.50843761     a    4
 5: -1.91331773     a    5
 6:  0.07850094     b    1
 7: -0.15922989     b    2
 8:  1.09806870     b    3
 9:  0.27995610     b    4
10:  0.45090842     b    5
11:  0.03400554     c    1
12: -0.34918734     c    2
13:  2.16602740     c    3
14: -0.04758261     c    4
15:  1.24869663     c    5

我不确定roll_sd功能来自哪里。但是,您可以计算例如zoo库的滚动平均值如下:

> library(zoo)
> setkey(DT, stock, time) # make sure data is sorted by time
> DT[, rollmean := rollmean(x, k = 3, fill = 0, align = "right"), 
+    by = .(stock)]
> DT
              x stock time   rollmean
 1:  0.25073356     a    1  0.0000000
 2: -0.24408170     a    2  0.0000000
 3: -0.87475856     a    3 -0.2893689
 4:  0.50843761     a    4 -0.2034676
 5: -1.91331773     a    5 -0.7598796
 6:  0.07850094     b    1  0.0000000
 7: -0.15922989     b    2  0.0000000
 8:  1.09806870     b    3  0.3391132
 9:  0.27995610     b    4  0.4062650
10:  0.45090842     b    5  0.6096444
11:  0.03400554     c    1  0.0000000
12: -0.34918734     c    2  0.0000000
13:  2.16602740     c    3  0.6169485
14: -0.04758261     c    4  0.5897525
15:  1.24869663     c    5  1.1223805

或等效

> DT[, `:=`(rollmean = rollmean(x, k = 3, fill = 0, align = "right")), 
+    by = .(stock)]
> DT
              x stock time   rollmean
 1:  0.25073356     a    1  0.0000000
 2: -0.24408170     a    2  0.0000000
 3: -0.87475856     a    3 -0.2893689
 4:  0.50843761     a    4 -0.2034676
 5: -1.91331773     a    5 -0.7598796
 6:  0.07850094     b    1  0.0000000
 7: -0.15922989     b    2  0.0000000
 8:  1.09806870     b    3  0.3391132
 9:  0.27995610     b    4  0.4062650
10:  0.45090842     b    5  0.6096444
11:  0.03400554     c    1  0.0000000
12: -0.34918734     c    2  0.0000000
13:  2.16602740     c    3  0.6169485
14: -0.04758261     c    4  0.5897525
15:  1.24869663     c    5  1.1223805

现在,数据中也有一个滚动平均功能。实现真的很简单。

DT[, rollmean := data.table::frollmean(x, n = 3, fill = 0, align = "right"), 
by = .(stock)]

两者的快速基准测试表明data.table版本更快一些(大多数时候)。

library(microbenchmark)
microbenchmark(a = DT[, rollmean := data.table::frollmean(x, n = 3, fill = 0, align = "right"), 
                      by = .(stock)]
               , b = DT[, rollmean := rollmean(x, k = 3, fill = 0, align = "right"),
                            by = .(stock)]
, times = 100L
)
Unit: milliseconds
expr    min      lq     mean  median     uq     max neval cld
   a 1.5695 1.66605 2.329675 1.79340 2.1980 39.3750   100  a 
   b 2.6711 2.82105 3.660617 2.99725 4.3577 20.3178   100   b

我遇到了同样的问题,该问题在数据处理过程中计算滚动标准。因此,我查看了此站点。而且我认为您的问题是使用DT $ MIDQUOTES而不是.sd $ midQuotes。.sd是一个数据。表包含每个组的X数据子集。Roll_sd函数来自软件包" rcpproll"。您可以这样尝试。

DT[, (sd = roll_sd(.SD$Midquotes, 20, fill=0, align = "right")), by = .(Stock)]

最新更新