2016-04-28 11 views
3

Ich hatte in letzter Zeit ein Haarausfall-Ereignis, bei dem ich nach vielen Schmerzen herausfand, dass die Funktion scale() bei Variablen mich daran hinderte, die predict-Funktion zu verwenden. Ich war ziemlich verblüfft, dass etwas so Einfaches wie das Zentrieren einer Variablen ihren Typ grundlegend verändern würde. Ich bin nicht gut darin, dies zu erklären, also ist es wahrscheinlich einfacher, zu sehen, was ich meine, indem ich einfach den Code unten ausführe.Zentrierende Variablen in R verhindert Vorhersage?

df = data.frame(
    a=runif(100,45,90), 
    b=runif(100,0,60), 
    y=runif(100,-30,60) 
) 

df$a.center=scale(df$a,scale=FALSE) 
df$b.center=scale(df$b,scale=FALSE) 

m<-lm(y ~ a.center + b.center, data=df) 

predict_df = data.frame(
    a.center=c(-10,10), 
    b.center=c(-5,5) 
) 
predict_df$predicted = predict(m,predict_df) 

ich den Fehler:

Error: variables ‘a.center’, ‘b.center’ were specified with different types from the fit 

verglichen, die zu diesem Code, der nicht zentrierten Variablen nicht verwendet und arbeitet als es soll:

m2<-lm(y ~ a + b, data=df) 
predict_df2 = data.frame(
    a=c(-10,10), 
    b=c(-5,5) 
) 
predict_df2$predicted = predict(m2,predict_df2) 

Ich habe auch bemerkt, dass wenn Sie str(df) tun, dass die zentrierten Variablen etwas haben, das "attr" unter ihnen heißt:

'data.frame': 100 obs. of 5 variables: 
$ a  : num 71.4 57.1 83.9 49 65 ... 
$ b  : num 54.56 16.76 52.43 34.11 2.43 ... 
$ y  : num -14.1 -20.8 31.3 -23 51.1 ... 
$ a.center: num [1:100, 1] 2.51 -11.77 14.96 -19.89 -3.87 ... 
..- attr(*, "scaled:center")= num 68.9 
$ b.center: num [1:100, 1] 23.31 -14.49 21.18 2.86 -28.82 ... 
..- attr(*, "scaled:center")= num 31.3 

Also meine Frage ist: Was zum Teufel passiert hier? Sollte ich nur die scale Funktion nicht verwenden? Gibt es eine einfache Lösung dafür, und was ist das "attr", was ich in str(df) sehe?

Antwort

2

Ich würde weiterhin Maßstab verwenden, die Ihnen die folgenden strukturierten Datenrahmen gibt (die durch Zentrieren erzeugt zwei Matrizen enthält, ist dies die Vignette erwähnt)

'data.frame': 100 obs. of 5 variables: 
$ a  : num 86.1 76.1 75.3 55.3 53.1 ... 
$ b  : num 48.99 5.99 11.34 56.47 12.9 ... 
$ y  : num -20.65 8.21 -21.6 13.36 -27.32 ... 
$ a.center: num [1:100, 1] 17.85 7.87 7.11 -12.93 -15.16 ... 
..- attr(*, "scaled:center")= num 68.2 
$ b.center: num [1:100, 1] 19.6 -23.4 -18 27.1 -16.5 ... 
..- attr(*, "scaled:center")= num 29.4 

as.vector Verwendung ist der Weg zu konvertieren zu gehen. Konvertiere sie einfach nach der Skalierung zurück.

nur neuer Schritt in dem Prozess

df$a.center<-as.vector(df$a.center) 
df$b.center<-as.vector(df$a.center) 

Dann ist Ihre resultierenden Daten wieder in der Struktur, die Sie erhofft hatten:

str(df) 
'data.frame': 100 obs. of 5 variables: 
$ a  : num 86.1 76.1 75.3 55.3 53.1 ... 
$ b  : num 48.99 5.99 11.34 56.47 12.9 ... 
$ y  : num -20.65 8.21 -21.6 13.36 -27.32 ... 
$ a.center: num 17.85 7.87 7.11 -12.93 -15.16 ... 
$ b.center: num 17.85 7.87 7.11 -12.93 -15.16 ... 

Dann wird Ihr lineares Modell und Prognosen laufen als Gewöhnlich, genommen von Ihrem Code direkt oben, mit den folgenden Ergebnissen:

predict_df 
a.center b.center predicted 
1  -10  -5 9.534243 
2  10  5 16.399051 

Ich würde definitiv weiterhin Maßstab verwenden, wenn Sie mit der Wahl zwischen den drei Methoden für jeden (TRUE, FALSE & ein numerischer Vektor) in der Vignette aufgeführt und wissen, wie Sie richtig auswählen, was Sie für Ihr bestimmtes Modell benötigen.

Der Grund, warum ich diese vorschlagen, ist genau wegen der attr.

attr ist ein Attribut der Matrix, die durch laufende Skala auf einem Vektor oder einem Rahmen zurückgegeben wurde. Es ist eine Möglichkeit, Informationen über die Transformation zu speichern, ohne sie in den eigentlichen Datenrahmen einzubeziehen. Es ist eine Art Metadaten über die transformierten Daten.

In diesem Fall ist das Attribut der Mittelwert der Spalte, nachdem die NA-Werte entfernt wurden. Dies ist der Wert, der zum Zentrieren der Daten verwendet wird. Sie können dies überprüfen, indem eine mittlere Berechnung zu tun, wie folgt:

mean(df$a) 
[1] 68.23281 

mean(df$b) 
[1] 29.38355  

Wenn Sie auch maßstäblich gewählt hatte, ein zweiter Wert für jeden gewesen wäre, die Standardabweichung der Säule nach NA-Werte werden entfernt.

R hat uns freundlicherweise die Zentrierungs- und Skalierungswerte für Sie notiert.

Je nachdem, wie Sie Ihre Vorhersage verwenden und wie genau Ihre Arbeit untersucht wird, ist es sinnvoll, diese Werte zu verwenden. Außerdem sind der Mittelwert und die Standardabweichung ein großartiger schneller Test, um zu sehen, ob Sie Ihre Daten vor der Modellierung richtig vorbereiten.

Auf jeden Fall lohnt sich der Aufwand der Konvertierung in einen Vektor oder Datenrahmen!

Wenn Sie dies selbst versuchen, stellen Sie sicher, dass Sie einen Startwert festlegen, damit Sie die Konvertierungen wiederholen können, ohne Werte zu verlieren.

Denken Sie darüber nach, den Datenrahmen vor der Verwendung von as.vector umzubenennen, damit Sie das Original mit den darin enthaltenen Attributen für die zukünftige Verwendung beibehalten und das lineare Modell auf dem konvertierten Satz ausführen können.

4

Schauen Sie sich die Klasse jeder Spalte des Datenrahmens, und Sie werden sehen das Problem:

> sapply(df, class) 
     a   b   y a.center b.center 
"numeric" "numeric" "numeric" "matrix" "matrix" 

Es scheint, dass scale liefert eine Matrix, und anscheinend der Datenrahmen ist glücklich, eine einzige zu akzeptieren -Spaltenmatrix in eine ihrer Spalten, aber lm betrachtet eine einspaltige Matrix nicht als äquivalent zu einem Vektor. Das ist eine Art seltsame und unglückliche Interaktion zwischen 3 Randfällen. Um es zu beheben, entweder vermeiden scale mit:

df$a.center <- df$a - mean(df$a) 
df$b.center <- df$b - mean(df$b) 

oder aber ausdrücklich das Ergebnis umwandeln zurück auf einen Vektor:

df$a.center <- as.vector(scale(df$a,scale=FALSE)) 
df$b.center <- as.vector(scale(df$b,scale=FALSE)) 

Alternativ können Sie die resultierende Matrix aus scale zurück in Spalten der Daten zuweisen Rahmen unter Verwendung von 2-D-Matrix-Indizierung Notation, die das richtige tut:

df[,c("a.center", "b.center")] <- scale(df[,c("a", "b")], scale=FALSE) 

Nach dem Sie das sehen sollen:

> sapply(df, class) 
     a   b   y a.center b.center 
"numeric" "numeric" "numeric" "numeric" "numeric" 

und Ihr Anruf an predict wird erfolgreich sein.

Verwandte Themen