VAR估计报错求助:eigen(companion)提示x含无穷或缺失值
拆解VAR滚动计算FEVD时的特征值报错问题
我来帮你排查这个困扰你的报错!你遇到的Error in eigen(companion) : infinite or missing values in 'x'确实和roots()函数密切相关——本质是VAR模型拟合出的伴随矩阵存在缺失值或无限值,导致特征值计算失败。下面是具体的排查方向和修复方案:
1. 先检查滚动窗口内的VAR拟合稳定性
你的滚动窗口是200条观测,但部分窗口的数据可能存在多重共线性、异常波动,导致VAR系数估计出现NA/Inf,进而引发后续的特征值计算报错。可以在循环里加一层前置检查:
for (i in 1:dim(CV)[3]) { var1 <- VAR(Y[i:(space+i-1),], p=nlag, type="const") # 新增:检查VAR系数是否存在异常值 if(any(is.na(coef(var1))) || any(is.infinite(coef(var1)))){ warning(paste("第", i, "个窗口的VAR拟合系数异常,跳过当前窗口")) CV[,,i] <- CV[,,(i-1)] next } if(any(roots(var1)>1)){ CV[,,i] <- CV[,,(i-1)] } else { CV[,,i] <- gfevd(var1, n.ahead=nfore)$fevd } if (i%%500==0) {print(i)} }
2. 预处理数据,清除隐藏的极端值
你已经检查了NA值,但极端大/小值也会导致VAR系数发散产生Inf值。可以对数据做标准化或缩尾处理:
# 方案1:标准化所有变量(均值为0,方差为1) Y_scaled <- scale(Y) # 方案2:缩尾处理,把上下1%的极端值替换为对应分位数 Y_winsorized <- apply(Y, 2, function(x){ qnt <- quantile(x, probs=c(0.01, 0.99), na.rm=TRUE) x[x < qnt[1]] <- qnt[1] x[x > qnt[2]] <- qnt[2] return(x) })
用处理后的数据集替换原Y再运行循环。
3. 动态调整VAR滞后阶数nlag
如果你的nlag设置过大,200条观测可能不足以支撑这么多参数的估计,导致系数不稳定。可以在每个窗口内用AIC准则动态选择最优滞后阶数:
for (i in 1:dim(CV)[3]) { # 先在当前窗口内选择最优滞后阶数 optimal_p <- VARselect(Y[i:(space+i-1),], lag.max=10, type="const")$selection["AIC(n)"] var1 <- VAR(Y[i:(space+i-1),], p=optimal_p, type="const") # 后续逻辑保持不变 if(any(roots(var1)>1)){ CV[,,i] <- CV[,,(i-1)] } else { CV[,,i] <- gfevd(var1, n.ahead=nfore)$fevd } if (i%%500==0) {print(i)} }
4. 用tryCatch捕获roots()的报错
避免单个窗口的报错中断整个循环,同时记录错误信息:
for (i in 1:dim(CV)[3]) { var1 <- VAR(Y[i:(space+i-1),], p=nlag, type="const") # 用tryCatch包裹roots检查逻辑 root_check <- tryCatch({ any(roots(var1) > 1) }, error = function(e){ warning(paste("第", i, "个窗口特征值计算失败:", e$message)) TRUE # 这里返回TRUE意味着用前一个窗口的值填充,可根据需求调整 }) if(root_check){ CV[,,i] <- CV[,,(i-1)] } else { CV[,,i] <- gfevd(var1, n.ahead=nfore)$fevd } if (i%%500==0) {print(i)} }
5. 先验证初始窗口的拟合情况
先单独跑第一个窗口的代码,确认基础拟合是否正常:
# 测试第一个滚动窗口 test_var <- VAR(Y[1:200,], p=nlag, type="const") print(coef(test_var)) # 检查系数是否有NA/Inf print(roots(test_var)) # 检查特征值计算是否正常 print(gfevd(test_var, n.ahead=nfore)$fevd) # 检查FEVD输出是否正常
如果第一个窗口就报错,说明你的基础数据或nlag设置有问题,优先解决这个再跑完整循环。
内容的提问来源于stack exchange,提问作者sardor mirzaev
相关产品推荐
相关产品推荐

