我试图使用library(financial)
为data.table
格式的给定现金流量计算每个观察值的净现值(NPV)。这是我的现金流:
library(data.table)
dt <- data.table(id=c(1,2,3,4), Year1=c(NA, 30, 40, NA), Year2=c(20, 30, 20 ,70), Year3=c(60, 40, 0, 10))
计算NPV并更新data.table,
library(financial)
npv <- apply(dt, 1, function(x) cf(na.omit(x[-1]), i = 20)$tab[, 'NPV'])
dt[, NPV:=npv]
返回,
id Year1 Year2 Year3 NPV
1: 1 NA 20 60 70.00000
2: 2 30 30 40 82.77778
3: 3 40 20 0 56.66667
4: 4 NA 70 10 78.33333
如何使用函数cf
直接将结果更新到data.table
中的每一行?
仅供参考:在我的真实数据集中,有超过50列
答案 0 :(得分:1)
我们可以尝试基于联接的方法
class Portfolio < ApplicationRecord
has_many :positions, dependent: :destroy
has_many :movements, through: :positions
belongs_to :user
validates :name,
presence: { message: "must be given." }
def portfolio_value
amount = positions.collect{|position|
position.quanity * position.value }.sum.round(2)
end
end
答案 1 :(得分:0)
重写cf
函数以仅计算所需的部分将显着加快 :
dt[, NPV := {x <- na.omit(unlist(.SD)); sum(x * sppv(20,0:(length(x)-1)))}, by=id]
# id Year1 Year2 Year3 NPV
#1: 1 NA 20 60 70.00000
#2: 2 30 30 40 82.77778
#3: 3 40 20 0 56.66667
#4: 4 NA 70 10 78.33333
事实上,现在这可能是矢量化了......嗯,让我想想!
答案 2 :(得分:0)
我们可以尝试在此示例中使用我们自己的npv
函数。
dcf <- function(x, r, t0=FALSE){
# calculates discounted cash flows (DCF) given cash flow and discount rate
#
# x - cash flows vector
# r - vector or discount rates, in decimals. Single values will be recycled
# t0 - cash flow starts in year 0, default is FALSE, i.e. discount rate in first period is zero.
if(length(r)==1){
r <- rep(r, length(x))
if(t0==TRUE){r[1]<-0}
}
x/cumprod(1+r)
}
npv <- function(x, r, t0=FALSE){
# calculates net present value (NPV) given cash flow and discount rate
#
# x - cash flows vector
# r - discount rate, in decimals
# t0 - cash flow starts in year 0, default is FALSE
sum(dcf(x, r, t0))
}
现在,只要您想要apply(x,1,f)
,melt
/ gather
/ nest
。
除非您打算完全误导数据的用户,否则在计算NPV时绝不应丢弃NA
。这意味着您正在将现金流量折现到不同的时间点。将NA
替换为0。我还看到你打算使用的套餐,将现金流量折扣到第0年,基本上意味着第一笔现金流量(在第1年)不打折。
library(data.table)
npv_dt <- melt(dt, id.vars = "id")[is.na(value), value:=0][order(variable), .(NPV=npv(x=value, r=0.2, t0=TRUE)), by="id"]
setkey(dt, id)
setkey(npv_dt, id)
npv_dt[dt]
#> id NPV Year1 Year2 Year3
#> 1: 1 58.33333 NA 20 60
#> 2: 2 82.77778 30 30 40
#> 3: 3 56.66667 40 20 0
#> 4: 4 65.27778 NA 70 10