R语言计算多时间跨度基金CAGR:变量列引用错误排查
计算私募股权基金CAGR的R代码问题
我有Calpers私募股权基金的多年业绩数据,已清洗合并成包含186条单基金投资记录的表格。部分基金有5年数据,多数是4年及以下。需要用公式CAGR= (Latest/First)^(1/n)-1,基于每条记录的最早和最晚数据计算CAGR。数据列名为2017、2018、2019、2020、2021。
尝试的实现步骤
- 定位数据列:
idx<- which(startsWith(names(calperMV),"2")) # 定位CAGR计算所需的列 idx <- rev(idx) # 匹配NA列的计数顺序
此时idx值为(6,5,4,3,2),对应2021-2020-2019-2018-2017的列序号。
- 统计每行NA数量得到
indx(NA均从左到右排列),尝试用!!sym()结合列名索引调用对应列计算CAGR:
calperMV %>% rowwise() %>% mutate(CAGR=`2021`/!!sym((colnames(.)[idx[indx]])^(1/(5-indx))-1))))
遇到的错误
执行上述代码时触发递归错误:
Error in local_error_context(dots = dots, .index = i, mask = mask) : promise already under evaluation: recursive default argument reference or earlier problems?
我已经通过测试代码验证索引能正确获取列名和对应数值,但完整计算CAGR时仍出现该错误。
解决方案
方法1:自动提取首尾值(推荐)
不需要手动统计NA数量,直接对每行的年份列提取非NA的最早/最晚值,再计算CAGR:
library(dplyr) # 定义年份列集合 year_cols <- c("2017", "2018", "2019", "2020", "2021") calperMV <- calperMV %>% rowwise() %>% mutate( # 提取该行第一个非NA值(最早业绩数据) first_val = first(na.omit(c_across(all_of(year_cols)))), # 提取该行最后一个非NA值(最新业绩数据) last_val = last(na.omit(c_across(all_of(year_cols)))), # 计算有效数据的年数 n_years = length(na.omit(c_across(all_of(year_cols)))), # 计算CAGR,年数为1时返回NA避免除以0 CAGR = ifelse(n_years > 1, (last_val / first_val)^(1/(n_years - 1)) - 1, NA) ) %>% ungroup()
方法2:修复原代码的语法与逻辑错误
原代码存在括号不匹配、!!sym()使用场景错误、公式逻辑错位三个问题,修正后如下:
# 假设indx已正确统计每行左侧连续NA的数量 calperMV <- calperMV %>% rowwise() %>% mutate( # 动态获取最早数据的列名(根据idx倒序和indx的定义调整索引) first_col = colnames(.)[idx[indx + 1]], # 用get()在rowwise环境下动态取列值,替代!!sym() first_val = get(first_col), # 按正确公式计算CAGR CAGR = (`2021` / first_val)^(1/(5 - indx)) - 1 ) %>% ungroup()
注意:此方法依赖
indx的准确定义,需确保5 - indx等于有效数据的年数。
错误原因说明
- 语法错误:原代码中
mutate的表达式括号嵌套混乱,导致解析失败 - 函数使用错误:
!!sym()用于提前解析列名,无法在rowwise()的逐行环境中动态引用每行的列名,改用get()更合适 - 公式逻辑错误:原代码把指数运算错误嵌套到了列名引用中,正确逻辑应为先计算
(最新值/最早值),再进行指数运算
内容的提问来源于stack exchange,提问作者xtufer
相关产品推荐
相关产品推荐

