Ricevo caricamenti "saltellanti" in PCA pieghevole in R. Posso aggiustarlo?


20

Ho 10 anni di dati sui rendimenti giornalieri per 28 valute diverse. Desidero estrarre il primo componente principale, ma piuttosto che far funzionare PCA per tutti i 10 anni, desidero aprire nuovamente una finestra di 2 anni, perché i comportamenti delle valute si evolvono e quindi desidero riflettere questo. Tuttavia ho un grosso problema, cioè che entrambe le funzioni princomp () e prcomp () passano spesso da caricamenti positivi a negativi nelle analisi adiacenti PCA (cioè a 1 giorno di distanza). Dai un'occhiata alla tabella di caricamento per la valuta EUR:

inserisci qui la descrizione dell'immagine

Chiaramente non posso usarlo perché i caricamenti adiacenti passeranno da positivo a negativo, quindi la mia serie che li utilizza sarà errata. Ora dai un'occhiata al valore assoluto del caricamento della valuta in EUR:

inserisci qui la descrizione dell'immagine

Il problema è ovviamente che non riesco ancora a usarlo perché puoi vedere dal grafico in alto che il caricamento va da negativo a positivo e viceversa, una caratteristica che devo preservare.

Esiste un modo per aggirare questo problema? Posso forzare l'orientamento degli autovettori ad essere sempre lo stesso nei PCA adiacenti?

A proposito, questo problema si verifica anche con la funzione FactoMineR PCA (). Il codice per il rollapply è qui:

rollapply(retmat, windowl, function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right") -> princomproll

3
Potresti spiegare cosa intendi per "orientamento" dell'autovettore? Per quanto ne so, non esiste una cosa intrinseca ai dati. (Questo è uno dei motivi per cui software diversi produrranno autovettori normalizzati diversi.) Quindi sembra che tu stia chiedendo qualcosa che non esiste ed è insignificante.
whuber

1
Bene, un giorno riceverò caricamenti come questo: EUR -0,2 ZAR +0,8 USD +0,41 ..... 28 valute. E il giorno successivo riceverò EUR +0,21 ZAR -0,79 USD -0,4 ecc. Quindi l'asse su cui il PCA ha scelto di ruotare i dati è orientato esattamente al contrario del giorno 2, rispetto al giorno 1. Ciò sta causando questi salti di caricamento e vorrei evitarlo, in qualche modo ...... Mi scuso se la mia terminologia è fuorviante. Comprendo che il codice PCA non si preoccupa realmente dell'orientamento dell'asse fintanto che è coerente tra i caricamenti in un giorno , ma ho bisogno che sia coerente per più giorni.
Thomas Browne,

1
tenendo presente che da un giorno all'altro, data una finestra mobile di 2 anni sui dati giornalieri, dovremmo avere un PCA molto, molto simile.
Thomas Browne,

Penso che il motivo per cui hai un problema sia che questa idea non ha senso. Non ho altra soluzione se non quella di cercare qualcosa di diverso che possa raggiungere i tuoi obiettivi (non sono sicuro di cosa siano) ed è ragionevole.
Michael R. Chernick,

EUR -0.2 ZAR +0.8 USD +0.41e EUR +0.21 ZAR -0.79 USD -0.4 sono molto simili. Basta invertire l'accesso in uno dei due risultati.
ttnphns,

Risposte:


22

Ogni volta che la trama salta troppo, invertire l'orientamento. Un criterio efficace è questo: calcolare la quantità totale di salti su tutti i componenti. Calcola la quantità totale di salti se il prossimo autovettore viene negato. Se quest'ultimo è inferiore, negare l'autovettore successivo.

Ecco un'implementazione. (Non ho familiarità con zoo, che potrebbe consentire una soluzione più elegante.)

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

Ad esempio, facciamo una passeggiata casuale in un gruppo ortogonale e agitiamo un po 'per interesse:

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,]
}

Ecco il PCA a rotazione:

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

Originale

Ora la versione fissa:

plot(amend(result))

modificato


tiovio+1io+1vioio1-1vio+1. Il tuo algoritmo sembra essere un po 'diverso. Funzionerebbe allo stesso modo?
ameba dice di ripristinare Monica

@amoeba Anche se non sono del tutto sicuro di quello che stai facendo, sembra che alcune delle idee discusse nella risposta di David J. Harris e nei commenti che seguono. Vedi, in particolare, il mio commento su stats.stackexchange.com/questions/34396/… .
whuber

2
@Art, quindi, come ho capito, vuoi correggere il segno del componente in base ad alcune preferenze esterne (esterne a PCA). Va bene, ma è così che dovresti affrontarlo. Per prima cosa fai la cosa scorrevole su PCA, assicurandoti che i segni siano coerenti. E quindi decidere, in base ad alcuni criteri aggiuntivi, se capovolgere l'intero componente o meno. Ad esempio, è possibile correlarlo con la tendenza dell'euro e se la correlazione è negativa, capovolgere il componente. O qualcosa di simile. Ciò dipende interamente dall'applicazione specifica e dalla conoscenza del dominio.
ameba dice che ripristini Monica il

1
Sono d'accordo con l'interpretazione e la raccomandazione di @ amoeba.
whuber

1
@amoeba: sì, hai ragione, anche se, ingenuamente, ho pensato che potesse esserci una soluzione generica che non dipende da specifiche serie temporali, qualcosa come "il vero orientamento del vettore" :), grazie per l'aiuto e suggerimenti
Anonimo il

8

@whuber ha ragione sul fatto che non esiste un orientamento intrinseco ai dati, ma è comunque possibile imporre che gli autovettori abbiano una correlazione positiva con un vettore di riferimento.

Ad esempio, potresti rendere positivi i caricamenti per USD su tutti i tuoi autovettori (ad esempio, se il caricamento di USD è negativo, capovolgi i segni dell'intero vettore). La direzione generale del tuo vettore è ancora arbitraria (dal momento che avresti potuto usare EUR o ZAR come riferimento), ma i primi assi del tuo PCA probabilmente non salteranno altrettanto - soprattutto perché le finestre rotanti sono così lungo.


7
Buona idea. L'ho provato prima (probabilmente mentre stavi postando questa risposta :-). Il problema è che gli altri caricamenti possono saltare. Per risolvere questo problema, basare la scelta del segno sul caricamento più grande. Ancora nessun dado: i caricamenti possono ancora saltare. Il trucco è in ogni momento scegliere l'orientamento che crea il minor disturbo nel vettore dei caricamenti della volta precedente.
whuber

4
@whuber Bel lavoro.
David J. Harris,

1
Corretto, il segno dei caricamenti non ha importanza (orientamento). Qualcosa che non è stato affrontato è che se si esegue questa operazione su diversi pacchetti software, le differenze tra i pacchetti sono che un programma può comportare segni negativi (positivi) su carichi particolari mentre un altro risultati segni positivi (negativi) per gli stessi carichi. Pertanto, i segni dei risultati finali nel grafico delle 3 serie sopra potrebbero essere invertiti quando si utilizza un altro pacchetto. Anche i caricamenti dei vettori di riferimento potrebbero presentare una modifica del segno e questa soluzione non sarebbe errata.
JoleT,

@LEP: ho riscontrato lo stesso problema con l'inversione, forse hai già trovato la soluzione a questo problema - come scoprire che il primo vettore è corretto e assicurarti che il resto sia allineato correttamente ad esso - quant.stackexchange.com/questions / 3094 / ... ?
Anonimo il

Fintanto che la matrice non è singolare e nessuno degli autovalori è zero, la maggior parte dei risultati dell'algoritmo dovrebbe essere la stessa, fatta eccezione per una variazione di 180 gradi nei segni - che non è garantita.
JoleT,

1

Quello che ho fatto è stato calcolare la distanza L1 tra autovettori successivi. Dopo aver normalizzato questa matrice ho scelto la soglia del punteggio az, ad esempio 1, in modo che se in ogni nuovo rotolamento la variazione è superiore a questa soglia, capovolgo l'autovettore, i fattori e i carichi per avere coerenza nella finestra di rotolamento. Personalmente non mi piace forzare i segni dati in alcune correlazioni poiché possono essere molto volatili a seconda dei driver macro.

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.