Vẽ một đường hồi quy piecewise


10

Có cách nào để vẽ đồ thị đường hồi quy của mô hình từng phần như thế này, ngoài việc sử dụng linesđể vẽ riêng từng phân đoạn hoặc sử dụng geom_smooth(aes(group=Ind), method="lm", fill=FALSE)không?

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

Cảm ơn bạn.

Câu trả lời:


6

Cách duy nhất tôi biết làm thế nào để thực hiện điều này một cách dễ dàng là dự đoán từ mô hình trên phạm vi sqftvà vẽ đồ thị dự đoán. Không có một cách chung nào với ablinehoặc tương tự. Bạn cũng có thể xem gói được phân đoạn sẽ phù hợp với các mô hình này và cung cấp cơ sở hạ tầng âm mưu cho bạn.

Làm điều này thông qua dự đoán và đồ họa cơ sở. Đầu tiên, một số dữ liệu giả:

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)

Phù hợp với mô hình:

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

Tạo một số dữ liệu để dự đoán và dự đoán:

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))

Vẽ các đường hồi quy:

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)

Bạn có thể mã hóa hàm này thành một hàm đơn giản - bạn chỉ cần các bước trong hai đoạn mã trước - mà bạn có thể sử dụng thay cho 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)
}

Sau đó:

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)

Qua gói phân khúc

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")

Với những dữ liệu này, nó không ước tính điểm dừng tại mean(sqft), nhưng các phương thức plotlinestrong gói đó có thể giúp bạn thực hiện một cái gì đó chung chung hơn là myablinethực hiện công việc này cho bạn diretcly từ lm()mô hình được trang bị .

Chỉnh sửa: Nếu bạn muốn phân đoạn để ước tính vị trí của điểm dừng, sau đó đặt 'psi'đối số thành NA:

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

Sau đó segmentedsẽ thử định K = 10lượng sqft, với Kviệc được đặt seg.control()và mặc định 10. Xem ?seg.controlđể biết thêm.


@Gavin (+1) Phản hồi đầy đủ hơn nhiều so với của tôi; Đơn giản là tôi thích nó.
chl

@Gavin Phần "Qua gói được phân đoạn" không hoạt động đối với dữ liệu của tôi. Tôi nhận được "Không có điểm dừng ước tính" sau khi chạy segmentedlệnh.
George Dontas

@ gd047: Xin lỗi, có lỗi trong mã tôi đã hiển thị. Bạn cần cung cấp đối số seq.Zvới công thức một phía của (các) biến có mối quan hệ được phân đoạn với phản hồi. Tôi đã chỉnh sửa câu trả lời của mình để bao gồm seq.Z = ~ sqftvà thêm một lưu ý về việc segmentedchọn giá trị psicho bạn.
Phục hồi Monica - G. Simpson

@ gd047 Tôi muốn xóa câu trả lời của mình vì câu hỏi này giải quyết câu hỏi ban đầu của bạn theo cách tốt hơn. Tâm trí sẽ chấp nhận cái này thay vì của tôi?
chl

@chl Tất nhiên, mặc dù tôi vẫn gặp lỗi: Lỗi trong mô hình objF if (model) <- mf: điều kiện có độ dài> 1 và chỉ phần tử đầu tiên sẽ được sử dụngmodel<mf:argumentisnotinterpretableaslogicalInaddition:Warningmessage:Inif(model)objF
George Dontas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.