r-我可以将tvm库中的XIRR函数应用于表中的每一行吗?现金流已经在那一行了



这是我的第一个问题,如果问题问得不完美,我提前道歉。我已经搜索了StackOverflow(&Google),但找不到我要找的东西。此外,我是R的新手,在学习的过程中我自己也在学习。

我的问题是:我正试图使用tvm中的XIRR函数来计算表中每一行的内部回报率。我能够让XIRR为一个单一的现金流工作。这是一个我能够去工作的例子。

# This is a sample that works
install.packages("tvm")
library(tvm)
x_CF <- c(-7500, 3000, 5000, 1200, 4000)
x_d <- as.Date(c("2016-01-01", "2016-02-01", "2016-04-15", "2016-08-01", "2017-03-26"))
xirr <- xirr(x_CF, x_d)

在我的特定场景中,我有一个表格,其中包含每个ID的周期性现金流和每行填充的日期。现金流在列cf1、cf2、cf3、cf(n)。。。日期在date1、date2、date3、date(n)…列中。。。现金流的数量和日期目前为14(n=14),但可能有所不同(即36、60等)。这是一个代码,它填充了我的大得多的表中的2行。

# This is just 2 rows of my data table where I manually write the values (the real table is much larger and is dynamically created with code)    
sample_data <-
matrix(
c(
"A",
"2016-01-31", "2016-02-29", "2016-03-31","2016-04-30","2016-05-31",
1000, 10, 20, -50, -1025,
"B",
"2016-01-31", "2016-02-29", "2016-03-31","2016-04-30", "2016-05-31",
1000, -50, 20, 10, -1025),
ncol = 11, byrow = TRUE)
colnames(sample_data) <-
c("SecId",
"date1", "date2", "date3", "date4", "date5",
"cf1", "cf2", "cf3", "cf4", "cf5")
sample_data <- tbl_df(sample_data)
sample_data <-
sample_data %>% mutate_at(vars(starts_with("cf")),
funs(as.integer))
sample_data <-
sample_data %>% mutate_at(vars(starts_with("date")),
funs(as.Date))

我想使用XIRR函数读取cf1:n和date1:n。结果应该是插入另一列(XIRR),并且计算值为A=0.1412532和B=0.1458380。

这可能吗,或者我应该研究其他功能吗?谢谢

EDIT-其他详细信息和对"同行"答案无效的回应

我的实际数据以超过550万行的长表格式显示现金流和日期。我之所以将它们转换为"弃用"表,是因为我最终要做的是创建一个滚动的月度内部收益率计算。我想,如果我在每一行上构建日期和现金流,那么我就可以避免对每一行直接应用XIRR进行循环。对于这么多的数据来说,创建包含ID/Date每次迭代的长表是不现实的(我不认为)。

使用拟议的代码,现金流和日期被合并为相同的ID,因此它不考虑滚动期间。我知道这在我最初的问题中没有解释。

此外,我有一些缺少现金流的时期显示NA(因为它们被变异为.number)。我需要XIRR在有NA的时候不进行计算来处理这个问题。我认为这可以通过summary命令中的is.na=TRUE来处理。

编辑#2:找到部分解决方案

玩过这个之后,我能够让XIRR函数为上面的示例数据工作。这是一个有效的代码,但我的实际数据需要很长时间。

calc_xirr <- sample_data %>% rowwise() %>%
do(data.frame(., xirr = tryCatch(xirr(unlist(.[7:11]), unlist(.[2:6]),lower=0,upper=1),
error = function(e) {NA}))) %>%
select(SecId, xirr)

我收到一条警告消息"警告消息:在bind_rows_(x,.id)中:不相等的因子级别:强制为字符",但计算是准确的。

我仍然面临的问题是,对于我的实际数据集来说,这有多慢。它运行很长时间(6个多小时),但确实产生了正确的结果。有没有任何方法可以使用并行处理或不使用行方式重写它,我认为这是一个循环操作,速度很慢。

首先,tbl_df似乎已被弃用,请改用as_tibbleas.tibble

我还更改了您的样本数据,因为我在应用ID"A"的数据时出错。我将样本数据定义如下。

sample_data <-
matrix(
c(
"A",
"2016-01-01",
"2016-02-01",
"2016-04-15",
"2016-08-01",
"2017-03-26",
-7500,
3000,
5000,
1200,
4000,
"B",
"2016-01-01",
"2016-02-01",
"2016-04-15",
"2016-08-01",
"2017-03-26",
-7500,
3000,
5000,
1200,
4000
),
ncol = 11,
byrow = TRUE
)
colnames(sample_data) <-
c("ID",
"date1",
"date2",
"date3",
"date4",
"date5",
"cf1",
"cf2",
"cf3",
"cf4",
"cf5")

我把代码分成两部分。第一部分是整理数据,第二部分是创建所需的值。

sample_data <- tbl_df(sample_data)
sample_data <-
sample_data %>% mutate_at(vars(starts_with("cf")),
funs(as.numeric),
vars(starts_with("date")),
funs(as.Date))
sample_data_dates <-
sample_data %>% select(starts_with("date"), ID) %>% gather(key, date, -ID) %>% mutate(index = gsub("date", "", key))
sample_data_cashflows <-
sample_data %>% select(starts_with("cf"), ID) %>% gather(key, cashflow,-ID) %>% mutate(index = gsub("cf", "", key))
sample_data <-
inner_join(
sample_data_dates %>% select(-key),
sample_data_cashflows %>% select(-key),
by = c("ID", "index")
) %>% select(-index)

在这之后,您就有了一个包含列名ID、日期和现金流的表。然后,您可以通过以下代码简单地计算函数xirr的结果值:

sample_data %>% group_by(ID) %>% summarise(xirr(cashflow,as.Date(date)))

最新更新