我正在使用R调查退货如何影响一个人的养老金账户。为了做到这一点,我正在计算养老金账户的发展,从25岁到70岁退休,1000个不同的回归情景。我使用变量费用(e),每月存款(m),以百分比(r)表示的回报,帐户余额(y)和以欧元(x)表示的回报。它们都存储在尺寸为46x1000的数据框中。
我已成功设法使用for循环计算它。然而,这是非常缓慢的,因为我正在做很多这些,我想知道是否有人有想法加快代码。我已尝试使用应用函数和矢量化但无法使其工作。我的问题是我必须在计算第i + 1年的数字之前计算第i年的数字。我在互联网上搜索了一个解决方案,但很难找到适用于我特定问题的答案。我应该注意到我还是R的新手。
A使用以下方法编写了代码的简化版本:
for (i in 3:46) {
x[i-1,]<-(y[i-1,]+m[i-1,]*6-0.5*e[i-1,])*r[i-1,]
y[i,]<-y[i-1,]+x[i-1,]-e[i-1,]+m[i-1,]*12
}
我希望有人能够提供帮助,并提前感谢。
祝你好运 拉斯穆斯
答案 0 :(得分:4)
你的过程看起来像是需要循环,因为每次迭代都依赖于它之前的循环。正如@Gregor de Cillia在评论中提到的那样,你可以用C ++来提高速度。
首先,设置一些数据。
set.seed(1)
e <- matrix( data = rnorm( n = 46000, mean = 1000, sd = 200 ),
nrow = 46,
ncol = 1000 )
m <- matrix( data = rnorm( n = 46000, mean = 2000, sd = 200 ),
nrow = 46,
ncol = 1000 )
r <- matrix( data = rnorm( n = 46000, mean = 4, sd = 0.5 ),
nrow = 46,
ncol = 1000 )
x <- matrix( data = NA_real_, nrow = 45, ncol = 1000 )
y <- matrix( data = NA_real_, nrow = 46, ncol = 1000 )
y[1,] <- rnorm( n = 1000, 10000, 1000 )
然后在Rcpp
文件中定义C ++函数。这将返回一个列表,其中包含两个矩阵x
和y
作为列表项:
List pension( NumericMatrix e,
NumericMatrix m,
NumericMatrix r,
NumericVector yfirstrow ) {
int ncols = e.cols();
int nrows = e.rows();
NumericMatrix x( nrows - 1, ncols );
NumericMatrix y( nrows, ncols );
y( 0, _ ) = yfirstrow;
for( int i = 1; i < nrows; i++ ) {
x( i-1, _ ) = ( y( i-1, _ ) + m( i-1, _ ) * 6 - 0.5 * e( i-1, _ ) ) * r( i-1, _ );
y( i, _ ) = y( i-1, _ ) + x( i-1, _ ) - e( i-1, _ ) + m( i-1, _ )* 12;
};
List ret;
ret["x"] = x;
ret["y"] = y;
return ret;
}
比较两种速度方法。
microbenchmark::microbenchmark(
R = {
for (i in 2:46) {
x[i-1,] <- unlist( (y[i-1,] + m[i-1,]*6 - 0.5*e[i-1,] ) * r[i-1,] )
y[i,]<- unlist( y[i-1,]+x[i-1,]-e[i-1,]+m[i-1,]*12 )
}
},
cpp = {
cppList <- pension( e, m, r, y[1,] )
},
times = 100
)
确保输出匹配:
> identical( x, cppList$x )
[1] TRUE
> identical( y, cppList$y )
[1] TRUE
速度测试结果:
Unit: microseconds
expr min lq mean median uq max neval
R 3309.962 3986.569 6961.838 5244.479 6219.215 96576.592 100
cpp 879.713 992.229 1266.014 1124.345 1273.691 3041.966 100
因此Rcpp
解决方案的速度提高了约5倍,但说实话,您所做的R
循环对于您所使用的数据集来说并不算太糟糕。使用(只有45次迭代,R循环的开销不是太大的障碍)。如果你真的需要速度,c ++可以提供帮助。