如何在R分段回归中约束拟合线起始点为(10,0)?
固定断点分段回归强制过指定起始点的解决方案
问题说明
需要对给定的债券数据集拟合分段线性回归,已固定断点为15、20、30,但要求拟合线必须起始于点(maturity=10, yield_change=0)。尝试变量变换时出现两个报错:
- 执行
segmented(model,seg.Z=~maturity,...)时,报错“object maturity not recognised” - 执行
segmented(model,seg.Z=~I(maturity-10),psi = list(I(maturity-10) = c(15,20,30)),...)时,出现语法错误
错误原因分析
- “object maturity not recognised”:通常是
segmented函数未正确从原模型的环境中识别变量,或数据传递路径出现问题。 - 语法错误:
psi参数的列表中不能直接使用I(maturity-10)作为元素名,R的语法不允许表达式作为列表元素名称。
解决方案
方法1:手动构造分段变量+约束回归(推荐,无需依赖segmented包)
既然已固定断点,直接手动构造分段变量,并通过去掉模型截距+自变量中心化的方式强制拟合线过(10,0),步骤如下:
- 中心化自变量到10,构造各断点对应的分段变量;
- 拟合无截距的线性模型,确保
maturity=10时预测值为0; - 生成包含指定起始点的预测数据并绘图。
完整代码
bond_data <- data.frame( yield_change = c(-1.2,-0.9,-1.8,-1.4,-1.8,-2.1,-2.3,-2.1,-2.5,-2.2,-2.4,-2.5,-2.4,-2.4, -3.0,-2.6,-5.1,-4.8,-4.9,-5.0,-5.0,-6.2,-6.1,-6.3,-5.0,-5.0), maturity =c(10.2795,10.8603,11.7753,12.3562,12.5205,13.3589,13.8630,14.2822,14.3589,15.3589, 15.8630,16.778,17.3616,17.8658,18.3616,21.8685,22.5288,23.8685,24.3644,25.3671, 26.8712,27.8712,28.8712,29.8740,44.3781,49.3836) ) # 构造满足约束的变量:中心化到maturity=10,生成分段变量 bond_data$mat_centered <- bond_data$maturity - 10 # mat_centered=0对应maturity=10 bond_data$seg15 <- pmax(bond_data$maturity - 15, 0) bond_data$seg20 <- pmax(bond_data$maturity - 20, 0) bond_data$seg30 <- pmax(bond_data$maturity - 30, 0) # 拟合无截距模型:强制maturity=10时yield_change=0 constrained_model <- lm(yield_change ~ 0 + mat_centered + seg15 + seg20 + seg30, data = bond_data) # 生成包含指定起始点的预测数据 xp <- c(10, 15, 20, 30, max(bond_data$maturity)) new_data <- data.frame(maturity = xp) new_data$mat_centered <- new_data$maturity - 10 new_data$seg15 <- pmax(new_data$maturity - 15, 0) new_data$seg20 <- pmax(new_data$maturity - 20, 0) new_data$seg30 <- pmax(new_data$maturity - 30, 0) # 预测并绘图 yp <- predict(constrained_model, new_data) plot(bond_data$maturity, bond_data$yield_change, pch=16, col="blue", ylim = c(-8,0), xlab="Maturity", ylab="Yield Change") lines(new_data$maturity, yp, col="red", lwd=2) points(10, 0, pch=18, col="red", cex=1.5) # 标记指定起始点
方法2:修正segmented包调用(保留segmented工作流)
如果必须使用segmented包,需先在数据框中生成变换后的变量,避免语法错误,同时确保预测包含指定起始点:
完整代码
bond_data <- data.frame( yield_change = c(-1.2,-0.9,-1.8,-1.4,-1.8,-2.1,-2.3,-2.1,-2.5,-2.2,-2.4,-2.5,-2.4,-2.4, -3.0,-2.6,-5.1,-4.8,-4.9,-5.0,-5.0,-6.2,-6.1,-6.3,-5.0,-5.0), maturity =c(10.2795,10.8603,11.7753,12.3562,12.5205,13.3589,13.8630,14.2822,14.3589,15.3589, 15.8630,16.778,17.3616,17.8658,18.3616,21.8685,22.5288,23.8685,24.3644,25.3671, 26.8712,27.8712,28.8712,29.8740,44.3781,49.3836) ) # 先生成变换后的变量,避免语法错误 bond_data$mat_10 <- bond_data$maturity - 10 # 拟合分段模型:断点对应mat_10的值为5(15-10)、10(20-10)、20(30-10) model <- lm(yield_change ~ mat_10, data = bond_data) segmented.model <- segmented(model, seg.Z=~mat_10, psi = list(mat_10 = c(5,10,20)), fixed.psi = c(5,10,20), control = seg.control(it.max = 0)) # 生成包含起始点的预测数据:mat_10=0对应maturity=10 xp_mat10 <- c(0, segmented.model$psi[,"Est."], max(bond_data$mat_10)) new_data <- data.frame(mat_10 = xp_mat10) yp <- predict(segmented.model, new_data) # 转换回maturity坐标并绘图 xp_maturity <- xp_mat10 + 10 plot(bond_data$maturity, bond_data$yield_change, pch=16, col="blue", ylim = c(-8,0)) lines(xp_maturity, yp, col="red", lwd=2) points(10, 0, pch=18, col="red", cex=1.5)
内容的提问来源于stack exchange,提问作者leonardo
相关产品推荐
相关产品推荐

