使用R,我想创建一个包含10,000个场景(行)和50个列的表,表示年度投资组合余额.每列的值应等于前一列的值减去一定的支出(例如,每年40,000美元),然后乘以随机生成的市场收益(表示为增长率).所有情景余额在零年开始时为1,000,000美元.
例如,市场在第1年回报率为6%(增长率为1.06).投资者有100万美元,花费40,000美元,留下960,000美元,然后赚取6%,留下一年的余额1,017,600美元.以下栏目(年份)以1,017,600美元开始,花费40,000美元,然后应用新的随机市场回报创建第二年余额.我重复50列(年)并重复该过程10,000个50年的情景.
我这样做循环如下:
# Set initial values
set.seed(27514)
n <- 10000 # number of scenarios
mu <- .05 # market return expectation
sigma <- .12 # market return volatility
portfolio <- 1000000 # $1,000000
yrs <- 50 # years of market returns and corresponding portfolio balances
spend <- 40000 # dollar amount to spend annually
balances <- matrix(nrow=n,ncol=yrs)
# function newbalance returns a portfolio balance for the current year (column) by subtracting an amount spent from the portfolio's
# previous balance (column - 1) and then applying the current year's market return to the remaining balance. If the
# new balance is negative, it is changed to zero.
newBalance <- function (lastYearBal,currentReturn,spend) { max(0,(lastYearBal - spend) * currentReturn) }
# Create table of n rows and (yrs = 50) columns of random market returns, expressed as growth rates (1.0 plus return)
marketReturns <- matrix(rlnorm(n*yrs,mu,sigma), n, yrs)
# Create 50 columns of n rows of portfolio balances based on the market returns matrix and constant annual spending = spend
for (i in 1:n) {
for (j in 1:yrs) {
if (j == 1) {oldBalance <- portfolio}
else {oldBalance <- balances[i,j-1]}
balances[i,j] <- newBalance(oldBalance,marketReturns[i,j],spend)
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种"更好"的方式来做到这一点,并且更好的意思是1)更清楚的是有人理解代码,2)更快,并且,希望,3)两者.
我刚刚开始使用dplyr并想知道是否有办法用Mutate做这个,也许.
建议大加赞赏.
除了不进行矢量化之外,OP的循环是可以的max.我会把它写成
do.call(cbind,
Reduce(
function(x,y) pmax(0, (x - spend)*y),
as.data.frame(marketReturns),
init = portfolio,
accumulate = TRUE
)[-1]
)
Run Code Online (Sandbox Code Playgroud)
这使
[,1] [,2] [,3] [,4] [,5]
[1,] 1225023.5 1356133.0 1411918.2 1422467.3 1333403.1
[2,] 886324.3 1116834.2 1393490.6 1290055.2 1188176.0
[3,] 1263106.3 1211609.4 1187170.0 1256445.9 1129850.1
[4,] 751897.5 749431.7 637428.4 717144.9 795654.3
[5,] 972910.2 832125.1 852293.3 717697.8 664908.3
[6,] 994046.2 922805.8 880951.7 814622.0 674656.3
[7,] 1077494.7 970762.1 1097041.3 963056.8 834362.0
[8,] 1034696.9 1145020.8 1132916.7 1292145.0 1567837.9
[9,] 1042336.3 1107492.6 1204792.5 1196458.1 991649.2
[10,] 860172.0 830692.4 934326.0 945027.2 932220.1
Run Code Online (Sandbox Code Playgroud)
Reduce 是标题中问题的一个非常标准的工具:
创建具有前一列功能的列的表的更好方法?
Reduce迭代列表; 所以as.data.frame上面用来转换marketReturns成列的列表(也称为一个data.frame).pmax(...)从相同长度的多个向量中获取项目的"并行最大值".标量喜欢0并且portfolio默默地"回收"成为适当长度的载体.
在旁边.这个问题可以说比StackOverflow 更适合代码审查.虽然它是可重复的,但是示例数据太大而无法显示和检查这里的帖子,所以我已切换到n=10,yrs=5.