使用R的segmented包拟合分段回归时,如何限制第二段斜率非负?
实现带非负第二段斜率的分组分段线性回归
要在segmented包中实现按cyl分组、且第二段斜率非负的分段回归,核心是利用segmented()的constraint参数约束斜率变化量,结合初始模型的斜率计算约束下限。以下是修改后的完整代码及说明:
完整代码
library(tidyverse) library(segmented) library(broom) mtcars %>% nest_by(cyl) %>% mutate( # 先拟合基础线性模型,获取初始斜率 lm_base = list(lm(hp ~ disp, data = data)), init_slope = coef(lm_base)[["disp"]], # 设置断点初始值(用分组内disp的中位数,提升收敛效率) init_break = list(quantile(data$disp, 0.5)), # 拟合带约束的分段回归:保证第二段斜率 ≥ 0 seg_mod = list(segmented( lm_base, psi = init_break, # 约束斜率变化量U1的下限:初始斜率 + U1 ≥ 0 → U1 ≥ -init_slope constraint = matrix(c(-init_slope, Inf), nrow = 1), # 增加迭代次数,避免约束下收敛失败 control = seg.control(iter.max = 100) )), # 清理中间变量 lm_base = NULL, init_slope = NULL, init_break = NULL ) %>% summarize(augment(seg_mod))
关键步骤说明
- 基础模型拟合:先为每个分组拟合普通线性回归,提取初始斜率,用于计算约束的下限值。
- 断点初始值设置:用分组内
disp的中位数作为断点初始值,帮助segmented()更快收敛到合理的断点位置。 - 斜率约束:通过
constraint参数定义斜率变化量的范围。分段回归中,第二段斜率 = 初始斜率 + 斜率变化量U1,要求第二段斜率≥0,即U1 ≥ -初始斜率,因此约束矩阵的下限设为-init_slope,上限设为Inf(无上限)。 - 收敛控制:通过
seg.control(iter.max = 100)增加迭代次数,避免因约束导致的收敛失败。
验证结果
你可以通过以下代码查看每组的分段回归参数,确认第二段斜率是否符合非负要求:
# 提取每组的分段回归参数 mtcars %>% nest_by(cyl) %>% mutate( lm_base = list(lm(hp ~ disp, data = data)), init_slope = coef(lm_base)[["disp"]], init_break = list(quantile(data$disp, 0.5)), seg_mod = list(segmented(lm_base, psi = init_break, constraint = matrix(c(-init_slope, Inf), nrow=1), control = seg.control(iter.max=100))) ) %>% summarize(tidy(seg_mod))
内容的提问来源于stack exchange,提问作者Hanna
相关产品推荐
相关产品推荐

