我正在使用一个引用给定人组合价值的函数。要使用此功能,我需要遍历数据框的行并应用此功能:
x$cota <- 100
cotiza <- function(x){
for(i in 1:nrow(x)) {
if (i > 1){
x[i,]$cota <- ((x[i,]$pl - x[i,]$mov)/x[i-1,]$pl) * x[i-1,]$cota
}
return (x)
}
这是该函数应用于的数据框:
data pl mov cota
1 2018-01-01 500.0 250000 100
2 2018-01-02 525.0 0 100
3 2018-01-03 997.2 -100000 100
4 2018-01-04 500.0 0 100
5 2018-01-05 520.0 0 100
此数据帧上函数的输出应类似于:
data pl mov cota
1 2018-01-01 500.0 250000 100.00
2 2018-01-02 525.0 0 105.00
3 2018-01-03 997.2 -100000 20199.44
4 2018-01-04 500.0 0 10128.08
5 2018-01-05 520.0 0 10533.20
反正有功能使该函数向量化,以便可以将其应用于数据框吗?
答案 0 :(得分:3)
由于cota[3]
依赖于cota[2]
的更新后的值cota[1]
,因此您无法对该函数进行简单的矢量化。有时,您可以通过使用cumsum
,cumprod
或类似的累积函数(仍然是迭代的,但是在真正优化的代码中)作弊,但它依赖于“简单的迭代累积”。但是,在这种情况下,
cota[2] = cota[1] * (pl[2] - mov[2]) / pl[1],
cota[3] = cota[2] * (pl[3] - mov[3]) / pl[2]
如果替换cota[2]
,您会得到
(cota[1] * (pl[2] - mov[2]) / pl[1]) * (pl[3] - mov[3]) / pl[2]
有效
cota[1] * (pl[2]*pl[3] - pl[2]*mov[3] - pl[3]*mov[2] + mov[2]*mov[3]) / (pl[1] * pl[2])
不会立即将其借给简单的累积运算符。
一些函数提供了各种滚动窗口,特别是zoo::rollapply
,但是它们经常在幕后进行for
循环。 (从技术上讲,我相信大多数*apply
函数也在内部进行for
循环,尽管可能在内部进行 well 。)
如果您对此功能或类似功能有性能问题,则可以始终使用Rcpp
或类似的加速方法。 (一旦进入Rcpp
区域,您可能会发现原始的for
循环会击败矢量化代码,甚至是Rcpp
原生矢量化,尽管这在很大程度上取决于许多其他因素。 )
答案 1 :(得分:2)
1)使用最后在注释中可重复显示的输入,尝试使用cumprod
,如下所示:
cotiza2 <- function(x) {
n <- nrow(x)
if (n < 2) return(x)
transform(x, cota = cumprod(c(cota[1], (pl - mov)[-1] / pl[-n])))
}
cotiza2(x)
## data pl mov cota
## 1 2018-01-01 500.0 250000 100.00
## 2 2018-01-02 525.0 0 105.00
## 3 2018-01-03 997.2 -100000 20199.44
## 4 2018-01-04 500.0 0 10128.08
## 5 2018-01-05 520.0 0 10533.20
2)这不是矢量化的,但是比问题中的代码短,并且比(1)的技巧少。
cotiza3 <- function(x) {
n <- nrow(x)
if (n < 2) return(x)
within(x, for(i in 2:n) cota[i] <- (pl[i] - mov[i]) / pl[i-1] * cota[i-1])
}
cotiza3(x)
## data pl mov cota
## 1 2018-01-01 500.0 250000 100.00
## 2 2018-01-02 525.0 0 105.00
## 3 2018-01-03 997.2 -100000 20199.44
## 4 2018-01-04 500.0 0 10128.08
## 5 2018-01-05 520.0 0 10533.20
Lines <- "
data pl mov cota
1 2018-01-01 500.0 250000 100
2 2018-01-02 525.0 0 100
3 2018-01-03 997.2 -100000 100
4 2018-01-04 500.0 0 100
5 2018-01-05 520.0 0 100"
x <- read.table(text = Lines)
添加了(1)。