Tracciare una linea di regressione a tratti


10

Esiste un modo per tracciare la linea di regressione di un modello a tratti come questo, oltre a usare linesper tracciare ciascun segmento separatamente o usare 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

Grazie.

Risposte:


6

L'unico modo in cui so come farlo facilmente è prevedere dal modello attraverso la gamma sqfte tracciare le previsioni. Non esiste un modo generale con ablineo simile. Puoi anche dare un'occhiata al pacchetto segmentato che si adatta a questi modelli e ti fornisce l'infrastruttura di stampa.

In questo modo tramite previsioni e grafica di base. Innanzitutto, alcuni dati fittizi:

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)

Misura il modello:

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

Generare alcuni dati per prevedere e prevedere:

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

Traccia le linee di regressione:

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)

Puoi codificarlo in una semplice funzione - hai solo bisogno dei passaggi nei due blocchi di codice precedenti - che puoi usare al posto di 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)
}

Poi:

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)

Tramite il pacchetto segmentato

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

Con questi dati non stimare il punto di interruzione a mean(sqft), ma i metodi plote linesin quel pacchetto potrebbero aiutarti a implementare qualcosa di più generico che myablinefare questo lavoro per te direttamente dal lm()modello adattato .

Modifica: se si desidera che il segmento venga stimato per la posizione del punto di interruzione, impostare l' 'psi'argomento su NA:

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

Quindi segmentedproverà i K = 10quantili di sqft, con l' Kessere settato seg.control()e quale è il default 10. Vedi ?seg.controldi più.


@Gavin (+1) Risposta molto più completa della mia; Mi piace.
chl

@Gavin La sezione "Via il pacchetto segmentato" non ha funzionato per i miei dati. Ho ricevuto un "Nessun punto di interruzione stimato" dopo aver eseguito il segmentedcomando.
George Dontas,

@ gd047: ci scusiamo, c'è stato un errore nel codice che ho mostrato. È necessario fornire argomento seq.Zcon una formula unilaterale delle variabili che hanno una relazione segmentata con la risposta. Ho modificato la mia risposta per includere seq.Z = ~ sqfte ho aggiunto una nota sulla segmentedscelta dei valori psiper te.
Gavin Simpson,

@ gd047 Vorrei rimuovere la mia risposta poiché questa affronta la tua domanda originale in un modo migliore. Ti dispiacerebbe accettare questo invece del mio?
CHL

model<-mf:un'rgumentioSnotionterpretun'Bleun'Slogiocun'lionun'ddiotioon:Wun'rniongmeSSun'ge:ioniof(model)oBjF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.