it-swarm.com.de

Hinzufügen von verzögerten Variablen zu einem Lm-Modell?

Ich verwende lm für eine Zeitserie, die eigentlich ganz gut funktioniert und super schnell ist.

Nehmen wir an, mein Modell ist:

> formula <- y ~ x

Ich trainiere dies mit einem Trainingsset:

> train <- data.frame( x = seq(1,3), y = c(2,1,4) )
> model <- lm( formula, train )

... und ich kann Vorhersagen für neue Daten treffen:

> test <- data.frame( x = seq(4,6) )
> test$y <- predict( model, newdata = test )
> test
  x        y
1 4 4.333333
2 5 5.333333
3 6 6.333333

Das funktioniert super gut und es ist sehr schnell.

Ich möchte dem Modell verzögerte Variablen hinzufügen. Jetzt könnte ich dies durch Erweitern meines ursprünglichen Trainingssatzes tun:

> train$y_1 <- c(0,train$y[1:nrow(train)-1])
> train
  x y y_1
1 1 2   0
2 2 1   2
3 3 4   1

aktualisieren Sie die Formel:

formula <- y ~ x * y_1

... und das Training wird gut funktionieren:

> model <- lm( formula, train )
> # no errors here

Das Problem ist jedoch, dass es keine Möglichkeit gibt, "Vorhersagen" zu verwenden, da es nicht möglich ist, y_1 in einem Testsatz stapelweise zu füllen.

Nun, für viele andere Regressionssachen gibt es sehr bequeme Möglichkeiten, sie in der Formel auszudrücken, wie zum Beispiel poly(x,2) usw., und diese arbeiten direkt unter Verwendung der unveränderten Trainings- und Testdaten.

Ich frage mich also, ob es eine Möglichkeit gibt, verzögerte Variablen in der Formel auszudrücken, sodass predict verwendet werden kann. Im Idealfall:

formula <- y ~ x * lag(y,-1)
model <- lm( formula, train )
test$y <- predict( model, newdata = test )

... ohne die Trainings- und Testdatensätze erweitern zu müssen (nicht sicher, ob das das richtige Wort ist) und einfach predict direkt verwenden zu können?

19
Hugh Perkins

Schauen Sie sich z. das Paket dynlm , das Ihnen Verzögerungsoperatoren gibt. Im Allgemeinen haben die Aufgabenansichten zu Ökonometrie und Zeitreihen noch viel mehr zu bieten.

Hier ist der Anfang seiner Beispiele - eine Verzögerung von einem und zwölf Monaten:

R>      data("UKDriverDeaths", package = "datasets")
R>      uk <- log10(UKDriverDeaths)
R>      dfm <- dynlm(uk ~ L(uk, 1) + L(uk, 12))
R>      dfm

Time series regression with "ts" data:
Start = 1970(1), End = 1984(12)

Call:
dynlm(formula = uk ~ L(uk, 1) + L(uk, 12))

Coefficients:
(Intercept)     L(uk, 1)    L(uk, 12)  
      0.183        0.431        0.511  

R> 
13

Dem Vorschlag von Dirk zu dynlm folgend, konnte ich nicht genau sagen, wie ich das vorhersagen kann. Die Suche danach führte mich jedoch zu einem dyn-Paket über https://stats.stackexchange.com/questions/6758/1-step-ahead-predictions -with-dynlm-r-package

Nach einigen Stunden des Experimentierens entwickelte ich die folgende Funktion, um die Vorhersage zu handhaben. Es gab einige 'Gotchas auf dem Weg, z. B. Sie können scheinbar keine rbind-Zeitreihe darstellen, und das Ergebnis von Predicting wird durch start und eine ganze Reihe solcher Dinge ausgeglichen Ich benenne ein Paket, obwohl ich Dirk's Antwort bestätigt habe.

Eine funktionierende Lösung ist also:

  • verwenden Sie das Paket dyn
  • verwenden Sie zur Vorhersage die folgende Methode

predictDyn-Methode:

# pass in training data, test data,
# it will step through one by one
# need to give dependent var name, so that it can make this into a timeseries
predictDyn <- function( model, train, test, dependentvarname ) {
    Ntrain <- nrow(train)
    Ntest <- nrow(test)
    # can't rbind ts's apparently, so convert to numeric first
    train[,dependentvarname] <- as.numeric(train[,dependentvarname])
    test[,dependentvarname] <- as.numeric(test[,dependentvarname])
    testtraindata <- rbind( train, test )
    testtraindata[,dependentvarname] <- ts( as.numeric( testtraindata[,dependentvarname] ) )
    for( i in 1:Ntest ) {
       result <- predict(model,newdata=testtraindata,subset=1:(Ntrain+i-1))
       testtraindata[Ntrain+i,dependentvarname] <- result[Ntrain + i + 1 - start(result)][1]
    }
    return( testtraindata[(Ntrain+1):(Ntrain + Ntest),] )
}

Verwendungsbeispiel:

library("dyn")

# size of training and test data
N <- 6
predictN <- 10

# create training data, which we can get exact fit on, so we can check the results easily
traindata <- c(1,2)
for( i in 3:N ) { traindata[i] <- 0.5 + 1.3 * traindata[i-2] + 1.7 * traindata[i-1] }
train <- data.frame( y = ts( traindata ), foo = 1)

# create testing data, bunch of NAs
test <- data.frame( y = ts( rep(NA,predictN) ), foo = 1)

# fit a model
model <- dyn$lm( y ~ lag(y,-1) + lag(y,-2), train )
# look at the model, it's a perfect fit. Nice!
print(model)

test <- predictDyn( model, train, test, "y" )
print(test)

# Nice plot
plot(test$y, type='l')

Ausgabe:

> model

Call:
lm(formula = dyn(y ~ lag(y, -1) + lag(y, -2)), data = train)

Coefficients:
(Intercept)   lag(y, -1)   lag(y, -2)  
        0.5          1.7          1.3  

> test
             y foo
7     143.2054   1
8     325.6810   1
9     740.3247   1
10   1682.4373   1
11   3823.0656   1
12   8686.8801   1
13  19738.1816   1
14  44848.3528   1
15 101902.3358   1
16 231537.3296   1

Edit: hmmm, das ist aber super langsam. Selbst wenn ich die Daten in der Variablen subset auf einige wenige Zeilen des Datensatzes beschränke, dauert es ungefähr 24 Millisekunden pro Vorhersage oder für meine Aufgabe 0.024*7*24*8*20*10/60/60 = 1.792 hours: -O

5
Hugh Perkins

Versuchen Sie die ARIMA-Funktion. Der AR-Parameter ist für die automatische Regression, dh das verzögerte y. Mit xreg = können Sie andere X-Variablen hinzufügen. Sie können Vorhersagen mit Predict.ARIMA erhalten. 

1
PL84

Hier ist ein Gedanke:

Warum erstellen Sie keinen neuen Datenrahmen? Füllen Sie einen Datenrahmen mit den benötigten Regressoren. Sie könnten Spalten wie L1, L2, ..., Lp für alle Verzögerungen einer beliebigen Variablen haben, und dann können Sie Ihre Funktionen genau so verwenden, wie Sie es für einen Regressionsquerschnitts-Typ tun würden.

Da Sie Ihre Daten nicht jedes Mal bearbeiten müssen, wenn Sie Anpassungs- und Vorhersagefunktionen aufrufen, sondern die Daten einmal umgewandelt haben, werden sie erheblich schneller. Ich weiß, dass Eviews und Stata verzögerte Operatoren anbieten. Es ist wahr, dass es eine Bequemlichkeit gibt. Es ist aber auch ineffizient, wenn Sie nicht alle Funktionen wie 'lm' berechnen müssen. Wenn Sie einige Hunderttausende von Iterationen durchführen müssen und nur die Prognose oder die Prognose und den Wert von Informationskriterien wie BIC oder AIC benötigen, können Sie die Geschwindigkeit von "lm" übertreffen, indem Sie Berechnungen vermeiden, die Sie nicht tun würden Verwenden Sie - schreiben Sie einfach einen OLS-Schätzer in eine Funktion, und Sie können loslegen.

0
Stéphane