Ich bekomme in Rollapply PCA in R "nervöse" Ladungen. Kann ich das beheben?

20

Ich habe 10 Jahre tägliche Rückgabedaten für 28 verschiedene Währungen. Ich möchte die erste Hauptkomponente extrahieren, aber anstatt PCA für die gesamten 10 Jahre zu betreiben, möchte ich ein 2-Jahres-Zeitfenster einhalten, da sich das Verhalten der Währungen verändert und ich dies reflektieren möchte. Ich habe jedoch ein großes Problem: Sowohl die Funktionen princomp () als auch prcomp () springen in benachbarten PCA-Analysen häufig von positiven zu negativen Belastungen (dh im Abstand von einem Tag). Schauen Sie sich die Ladetabelle für die EUR-Währung an:

Bildbeschreibung hier eingeben

Dies kann ich natürlich nicht verwenden, da benachbarte Ladungen von positiv nach negativ springen und meine Serien, in denen sie verwendet werden, fehlerhaft sind. Schauen Sie sich nun den absoluten Wert der EUR-Währungsbelastung an:

Bildbeschreibung hier eingeben

Das Problem ist natürlich, dass ich dies immer noch nicht verwenden kann, da Sie aus der oberen Tabelle ersehen können, dass die Belastung manchmal von negativ nach positiv und zurück geht, eine Eigenschaft, die ich bewahren muss.

Kann ich dieses Problem irgendwie umgehen? Kann ich erzwingen, dass die Eigenvektororientierung in benachbarten PCAs immer gleich ist?

Dieses Problem tritt übrigens auch bei der Funktion FactoMineR PCA () auf. Der Code für die App ist hier:

rollapply(retmat, windowl, function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right") -> princomproll
Thomas Browne
quelle
3
Können Sie erklären, was Sie unter Eigenvektororientierung verstehen? Soweit ich weiß, gibt es nichts, was den Daten eigen ist . (Dies ist ein Grund, warum unterschiedliche Software unterschiedliche normalisierte Eigenvektoren erzeugt.) Es scheint also, als würden Sie nach etwas fragen, das nicht existiert und bedeutungslos ist.
whuber
1
Nun, eines Tages werde ich Ladungen wie diese bekommen: EUR -0,2 ZAR +0,8 USD +0,41 ..... 28 Währungen. Und am nächsten Tag bekomme ich EUR +0,21 ZAR -0,79 USD -0,4 usw. Die Achse, auf die der PCA die Daten dreht, ist am zweiten Tag genau umgekehrt ausgerichtet als am ersten Tag Diese Ladesprünge und ich möchte es irgendwie vermeiden ...... Entschuldigung, wenn meine Terminologie irreführend ist. Ich verstehe, dass der PCA-Code sich nicht wirklich um die Achsenorientierung kümmert, solange er an einem Tag über mehrere Tage hinweg konsistent ist.
Thomas Browne
1
Wenn wir uns vor Augen halten, dass wir von einem Tag auf den nächsten einen sehr, sehr ähnlichen PCA haben sollten, wenn wir ein rollierendes 2-Jahres-Fenster für die täglichen Daten haben.
Thomas Browne
Ich denke, der Grund, warum Sie ein Problem haben, ist, dass diese Idee keinen Sinn ergibt. Ich habe keine andere Lösung, als nach etwas anderem zu suchen, das Ihre Ziele erreichen kann (nicht sicher, was sie sind) und das vernünftig ist.
Michael R. Chernick
EUR -0.2 ZAR +0.8 USD +0.41und EUR +0.21 ZAR -0.79 USD -0.4 sind sehr sehr ähnlich. Sie kehren einfach das Vorzeichen in einem der beiden Ergebnisse um.
TTNPHNS

Antworten:

22

Wenn die Handlung zu stark springt, kehren Sie die Ausrichtung um. Ein wirksames Kriterium ist: Berechnen Sie die Gesamtanzahl der Sprünge für alle Komponenten. Berechnen Sie die Gesamtanzahl der Sprünge, wenn der nächste Eigenvektor negiert wird. Ist letzterer kleiner, negiere den nächsten Eigenvektor.

Hier ist eine Implementierung. (Ich kenne mich nicht aus zoo, was eine elegantere Lösung ermöglichen könnte.)

require(zoo)
amend <- function(result) {
  result.m <- as.matrix(result)
  n <- dim(result.m)[1]
  delta <- apply(abs(result.m[-1,] - result.m[-n,]), 1, sum)
  delta.1 <- apply(abs(result.m[-1,] + result.m[-n,]), 1, sum)
  signs <- c(1, cumprod(rep(-1, n-1) ^ (delta.1 <= delta)))
  zoo(result * signs)
}

Lassen Sie uns als Beispiel einen zufälligen Spaziergang in einer orthogonalen Gruppe machen und ihn aus Interesse ein wenig zittern:

random.rotation <- function(eps) {
  theta <- rnorm(3, sd=eps)
  matrix(c(1, theta[1:2], -theta[1], 1, theta[3], -theta[2:3], 1), 3)
}
set.seed(17)
n.times <- 1000
x <- matrix(1., nrow=n.times, ncol=3)
for (i in 2:n.times) {
  x[i,] <- random.rotation(.05) %*% x[i-1,]
}

Hier ist der rollende PCA:

window <- 31
data <- zoo(x)
result <- rollapply(data, window, 
  function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right")
plot(result)

Original

Nun die feste Version:

plot(amend(result))

Geändert

whuber
quelle
tichvich+1ich+1vichich1-1vich+1. Ihr Algorithmus scheint etwas anders zu sein. Würde es genauso funktionieren?
Amöbe sagt Reinstate Monica
@amoeba Obwohl ich nicht genau weiß, was Sie tun, klingt es nach einigen der Ideen, die in der Antwort von David J. Harris und den darauf folgenden Kommentaren diskutiert wurden. Siehe insbesondere meinen Kommentar unter stats.stackexchange.com/questions/34396/… .
Whuber
2
@Art, so wie ich es verstehe, möchten Sie das Vorzeichen der Komponente anhand einiger externer (PCA-externer) Einstellungen korrigieren. Dies ist in Ordnung, aber so sollten Sie es angehen. Führen Sie zuerst die gleitende PCA-Aktion aus, und stellen Sie sicher, dass die Zeichen konsistent sind. Und dann entscheiden Sie anhand einiger zusätzlicher Kriterien, ob Sie die gesamte Komponente spiegeln möchten oder nicht. Sie können es beispielsweise mit dem Eurotrend korrelieren, und wenn die Korrelation negativ ist, drehen Sie die Komponente um. Oder etwas ähnliches. Dies hängt ganz von Ihrer spezifischen Anwendung und Ihren Domain-Kenntnissen ab.
Amöbe sagt Reinstate Monica
1
Ich stimme der Interpretation und Empfehlung von @amoeba zu.
whuber
1
@amoeba: ja, da hast du recht, obwohl ich naiv gedacht habe, dass es eine generische Lösung geben könnte, die nicht von bestimmten Zeitreihen abhängt, so etwas wie "echte Orientierung des Vektors" :) trotzdem, danke für Hilfe und Vorschläge
Anonym
8

@whuber ist richtig, dass es keine Orientierung gibt, die den Daten eigen ist, aber Sie könnten immer noch erzwingen, dass Ihre Eigenvektoren eine positive Korrelation mit einem Referenzvektor haben.

Zum Beispiel könnten Sie die Aufladungen für USD auf allen Ihren Eigenvektoren positiv machen (dh, wenn die Aufladung des USD negativ ist, kippen Sie die Vorzeichen des gesamten Vektors). Die Gesamtrichtung Ihres Vektors ist immer noch willkürlich (da Sie stattdessen EUR oder ZAR als Referenz hätten verwenden können), aber die ersten Achsen Ihres PCA werden wahrscheinlich nicht annähernd so weit springen - insbesondere, weil Ihre rollenden Fenster dies sind lange.

David J. Harris
quelle
7
Gute Idee. Ich habe es zuerst versucht (wahrscheinlich, als du diese Antwort gepostet hast :-). Das Problem ist, dass die anderen Ladungen herumspringen können. Um dies zu beheben, stützen Sie die Vorzeichenauswahl auf die größte Belastung. Immer noch keine Würfel: Die Ladungen können immer noch springen. Der Trick besteht darin , zu jedem Zeitpunkt um die Orientierung zu wählen, die die geringste Störung in dem schafft Vektor der Belastungen von der vorhergehenden Zeit.
Whuber
4
@whuber Gute Arbeit.
David J. Harris
1
Richtig, das Vorzeichen von Belastungen spielt keine Rolle (Orientierung). Etwas, das nicht angesprochen wurde, war, dass, wenn Sie dies für verschiedene Softwarepakete ausführen, die Unterschiede zwischen den Paketen darin bestehen, dass ein Programm bei bestimmten Ladevorgängen zu negativen (positiven) Vorzeichen führen kann, während ein anderes zu positiven (negativen) Vorzeichen für dieselben Ladevorgänge führt. Daher können die Vorzeichen der Endergebnisse in der obigen Darstellung mit drei Reihen bei Verwendung eines anderen Pakets umgekehrt werden. Die Referenzvektorladungen könnten auch ein Vorzeichen ändern - und diese Lösung wäre nicht falsch.
JoleT
@LEP: Ich hatte das gleiche Problem mit der Inversion, vielleicht haben Sie bereits eine Lösung für dieses Problem gefunden - wie Sie herausfinden können, dass der erste Vektor korrekt ist, und ob der Rest richtig darauf ausgerichtet ist - quant.stackexchange.com/questions / 3094 /… ?
Anonym
Solange die Matrix nicht singulär ist und keiner der Eigenwerte Null ist, sollten die meisten Algorithmusergebnisse gleich sein, mit Ausnahme einer 180-Grad-Änderung der Vorzeichen - was nicht garantiert ist.
JoleT
1

Ich habe den L1-Abstand zwischen aufeinanderfolgenden Eigenvektoren berechnet. Nach der Normalisierung dieser Matrix wähle ich eine Bewertungsschwelle von z, z. B. 1, so dass ich bei einem neuen Wurf die Eigenvektoren, Faktoren und Belastungen umdrehe, um eine Konsistenz im Wurffenster zu erreichen. Persönlich mag ich es nicht, gegebene Zeichen in einigen Korrelationen zu erzwingen, da sie abhängig von den Makrotreibern sehr flüchtig sein können.

Raul Muñoz
quelle