这是我的第一个问题,因此,如果不是一个完美的问题,我谨向您道歉。我已经在Stack Overflow(&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。
这是可能的,还是我应该研究其他功能?谢谢!
编辑-其他详细信息和“同行”答案无效的原因
我的实际数据具有长表格式的现金流量和日期,其中有超过550万行。之所以将它们转换为“已弃用”表,是因为我最终想要做的是创建滚动的每月IRR计算。我想出了如果我在每一行上建立了日期和现金流,那么我就可以避免直接将XIRR直接应用于每一行。对于这样大量的数据(我不认为),创建包含ID / Date的每个迭代的长表是不现实的。
使用建议的代码,现金流和日期合并为相同的ID,因此不考虑滚动期间。我知道我的原始问题没有对此进行解释。
此外,我的现金流缺失的期间显示为NA(因为它们被突变为数字)。我需要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小时),但确实会产生正确的结果。有什么方法可以使用并行处理来重写它,也可以不逐行重写,我认为这是循环操作并且很慢。
答案 0 :(得分:0)
首先,tbl_df
似乎已被弃用,请改用as_tibble
或as.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)))