22 votos

Estoy recibiendo "jumpy" cargas en rollapply PCA en R. ¿Puedo solucionarlo?

Tengo 10 años de datos de rendimientos diarios para 28 divisas diferentes. Quiero extraer el primer componente principal, pero en lugar de aplicar el ACP a los 10 años completos, quiero aplicar una ventana de 2 años, porque el comportamiento de las divisas evoluciona y quiero reflejarlo. Sin embargo, tengo un problema importante, y es que tanto el princomp() y prcomp() Las funciones a menudo saltan de cargas positivas a negativas en análisis PCA adyacentes (es decir, con 1 día de diferencia). Eche un vistazo al gráfico de carga de la divisa EUR:

enter image description here

Claramente no puedo usar esto porque las cargas adyacentes saltarán de positivas a negativas, por lo que mi serie que las use será errónea. Ahora eche un vistazo al valor absoluto de la carga de la divisa EUR:

enter image description here

El problema es que aún no puedo utilizarlo porque, como se puede ver en el gráfico superior, la carga pasa a veces de negativa a positiva y viceversa, una característica que necesito conservar.

¿Hay alguna forma de evitar este problema? ¿Puedo forzar que la orientación del vector propio sea siempre la misma en los ACP adyacentes?

Por cierto, este problema también ocurre con la función PCA() de FactoMineR. El código para el rollapply está aquí:

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

26voto

jldugger Puntos 7490

Siempre que la trama salte demasiado, invierte la orientación. Un criterio eficaz es el siguiente: calcular la cantidad total de saltos en todos los componentes. Calcule la cantidad total de saltos si el siguiente vector propio es negado. Si es menor, niegue el siguiente vector propio.

He aquí una aplicación. (No estoy familiarizado con zoo que podría permitir una solución más 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)
}

A modo de ejemplo, hagamos un recorrido aleatorio en un grupo ortogonal y un poco de jitter por interés:

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

Aquí está el PCA rodante:

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

Original

Ahora la versión fija:

plot(amend(result))

Amended

7voto

Bou Puntos 1859

@whuber tiene razón en que no hay una orientación que sea intrínseca a los datos, pero aún así podrías hacer cumplir que tus vectores propios tengan correlación positiva con algún vector de referencia.

Por ejemplo, puede hacer que las cargas de USD sean positivas en todos sus vectores propios (es decir, si la carga de USD es negativa, invierta los signos de todo el vector). La dirección general de su vector sigue siendo arbitraria (ya que podría haber utilizado EUR o ZAR como referencia), pero los primeros ejes de su PCA probablemente no salten tanto, especialmente porque sus ventanas móviles son muy largas.

1voto

khoman Puntos 1

Lo que hice fue calcular la distancia L1 entre vectores propios sucesivos. Después de normalizar esta matriz, elijo un umbral de puntuación z, por ejemplo, 1, de modo que si en cualquier nuevo balanceo el cambio está por encima de este umbral, volteo el vector propio, los factores y las cargas con el fin de tener coherencia en la ventana de balanceo. Personalmente no me gusta forzar signos dados en algunas correlaciones ya que pueden ser muy volátiles dependiendo de los macro conductores.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X