我有一个关于根据条件计算滚动平均值/标准差的问题。说实话,这更像是一个语法问题,但是因为我认为它会慢慢减慢我的代码,我想我应该在这里问它以了解发生了什么。我有一些财务数据,其中包含Stock Name
,Midquotes
等列。我想根据库存计算滚动平均值和滚动标准差。
现在我想计算每只股票的波动率,这是通过采用前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
?
答案 0 :(得分:2)
我认为您的问题是您使用:=
函数,并在方括号内使用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
答案 1 :(得分:1)
现在data.table本身中还有一个滚动均值函数,有关详细信息,请参见github disscussion。实现非常简单。
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
答案 2 :(得分:0)
我在数据处理过程中遇到了计算滚动标准的相同问题,因此我查看了该站点。而且我认为您的问题是使用DT $ Midquotes而不是.SD $ Midquotes。 .SD是一个data.table,其中包含每个组的x数据的子集。而roll_sd函数来自“ RcppRoll”包。 您可以尝试这种方式。
DT[, (sd = roll_sd(.SD$Midquotes, 20, fill=0, align = "right")), by = .(Stock)]