绘制分段回归线


10

除了lines用于单独绘制每个段或使用之外,是否有办法绘制像这样的分段模型的回归线geom_smooth(aes(group=Ind), method="lm", fill=FALSE)

m.sqft <- mean(sqft)
model <- lm(price~sqft+I((sqft-m.sqft)*Ind))
# sqft, price: continuous variables, Ind: if sqft>mean(sqft) then 1 else 0

plot(sqft,price)
abline(reg = model)
Warning message:
In abline(reg = model) :
  only using the first two of 3regression coefficients

谢谢。

Answers:


6

我知道如何轻松做到这一点的唯一方法是根据模型在整个范围内进行sqft预测并绘制预测。没有通用的方法abline或类似方法。您还可以查看适合这些模型并为您提供绘图基础结构的分段软件包。

通过预测和基本图形执行此操作。首先,一些伪数据:

set.seed(1)
sqft <- runif(100)
sqft <- ifelse((tmp <- sqft > mean(sqft)), 1, 0) + rnorm(100, sd = 0.5)
price <- 2 + 2.5 * sqft
price <- ifelse(tmp, price, 0) + rnorm(100, sd = 0.6)
DF <- data.frame(sqft = sqft, price = price,
                 Ind = ifelse(sqft > mean(sqft), 1, 0))
rm(price, sqft)
plot(price ~ sqft, data = DF)

拟合模型:

mod <- lm(price~sqft+I((sqft-mean(sqft))*Ind), data = DF)

生成一些数据以进行预测和预测:

m.sqft <- with(DF, mean(sqft))
pDF <- with(DF, data.frame(sqft = seq(min(sqft), max(sqft), length = 200)))
pDF <- within(pDF, Ind <- ifelse(sqft > m.sqft, 1, 0))
pDF <- within(pDF, price <- predict(mod, newdata = pDF))

绘制回归线:

ylim <- range(pDF$price, DF$price)
xlim <- range(pDF$sqft, DF$sqft)
plot(price ~ sqft, data = DF, ylim = ylim, xlim = xlim)
lines(price ~ sqft, data = pDF, subset = Ind > 0, col = "red", lwd = 2)
lines(price ~ sqft, data = pDF, subset = Ind < 1, col = "red", lwd = 2)

您可以将其编码为一个简单的函数-您只需要前面两个代码块中的步骤-可以代替以下代码使用abline

myabline <- function(model, data, ...) {
    m.sqft <- with(data, mean(sqft))
    pDF <- with(data, data.frame(sqft = seq(min(sqft), max(sqft),
                                            length = 200)))
    pDF <- within(pDF, Ind <- ifelse(sqft > m.sqft, 1, 0))
    pDF <- within(pDF, price <- predict(mod, newdata = pDF))
    lines(price ~ sqft, data = pDF, subset = Ind > 0, ...)
    lines(price ~ sqft, data = pDF, subset = Ind < 1, ...)
    invisible(model)
}

然后:

ylim <- range(pDF$price, DF$price)
xlim <- range(pDF$sqft, DF$sqft)
plot(price ~ sqft, data = DF, ylim = ylim, xlim = xlim)
myabline(mod, DF, col = "red", lwd = 2)

通过分段包装

require(segmented)
mod2 <- lm(price ~ sqft, data = DF)
mod.s <- segmented(mod2, seg.Z = ~ sqft, psi = 0.5,
                   control = seg.control(stop.if.error = FALSE))
plot(price ~ sqft, data = DF)
plot(mod.s, add = TRUE)
lines(mod.s, col = "red")

对于这些数据,它不会估计处的断点mean(sqft),但该包中的plotlines方法可能会帮助您实现比myabline从拟合lm()模型中直接为您完成这项工作更通用的功能。

编辑:如果要分段以估计断点的位置,则将'psi'参数设置为NA

mod.s <- segmented(mod2, seg.Z = ~ sqft, psi = NA,
                   control = seg.control(stop.if.error = FALSE))

然后segmented将尝试的K = 10分位数sqftK设置为seg.control(),默认为10。查看?seg.control更多。


@Gavin(+1)比我的回答更完整;我喜欢
chl

@Gavin“通过分段软件包”部分不适用于我的数据。运行segmented命令后,我得到了“没有断点估计” 。
George Dontas 2011年

@ gd047:抱歉,我显示的代码有错误。您需要为参数提供变量seq.Z的单边公式,这些变量与响应具有分段关系。我已经编辑了答案,以包括seq.Z = ~ sqft并添加了有关为您segmented选择值的注释psi
加文·辛普森,

@ gd047我想删除我的答案,因为这个答案可以更好地解决您的原始问题。介意代替我接受这个吗?
chl

@chl当然,即使我仍然遇到错误:if(model)objF -mf:错误 model <:条件长度> 1,并且只会使用第一个元素ØdË<-F一个[RGüËñŤ一世sñØŤ一世ñŤË[Rp[RËŤ一个bË一个sØG一世C一个一世ñ一个dd一世Ť一世Øñw ^一个[Rñ一世ñGËss一个GË一世ñ一世FØdËØbĴF
George Dontas 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.