Я получаю «скачкообразные» нагрузки в Rollapply PCA в R. Могу ли я это исправить?

20

У меня есть 10-дневные данные ежедневных возвратов по 28 различным валютам. Я хотел бы извлечь первый основной компонент, но вместо того, чтобы использовать PCA в течение всех 10 лет, я хочу перенести двухлетнее окно, потому что поведение валют меняется, и поэтому я хочу это отразить. Однако у меня есть серьезная проблема, заключающаяся в том, что функции princomp () и prcomp () часто переходят от положительной к отрицательной нагрузке в смежных анализах PCA (то есть с интервалом в 1 день). Посмотрите на график загрузки для валюты EUR:

введите описание изображения здесь

Понятно, что я не могу использовать это, потому что смежные загрузки будут переходить с положительного на отрицательный, поэтому моя серия, которая их использует, будет ошибочной. Теперь посмотрим на абсолютное значение загрузки валюты в евро:

введите описание изображения здесь

Проблема, конечно, в том, что я до сих пор не могу использовать это, потому что из верхней диаграммы видно, что загрузка действительно меняется с отрицательной на положительную и временами обратно, и эту характеристику мне нужно сохранить.

Есть ли способ, которым я могу обойти эту проблему? Могу ли я заставить ориентацию собственного вектора всегда быть одинаковой в смежных PCA?

Кстати, эта проблема также возникает с функцией FactoMineR PCA (). Код для rollapply здесь:

rollapply(retmat, windowl, function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right") -> princomproll
Томас Браун
источник
3
Не могли бы вы объяснить, что вы подразумеваете под "ориентацией" собственного вектора? Насколько я знаю, нет такой вещи, которая присуща данным. (Это одна из причин, по которой разное программное обеспечение будет создавать разные нормализованные собственные векторы.) Похоже, вы просите что-то, чего не существует и которое не имеет смысла.
whuber
1
В один прекрасный день я получу такие нагрузки: EUR -0,2 ZAR +0,8 USD +0,41 ..... 28 валют. А на следующий день я получу EUR +0.21 ZAR -0.79 USD -0.4 и т. Д. Таким образом, ось, на которую PCA выбрала для поворота данных, ориентирована как раз наоборот в день 2 по сравнению с днем ​​1. Это вызывает эти скачки загрузки, и я хочу как-то их избежать ...... Извинения, если моя терминология вводит в заблуждение. Я понимаю, что код PCA на самом деле не заботится об ориентации оси, если он согласован для нагрузок в один день , но мне нужно, чтобы он был согласованным в течение нескольких дней.
Томас Браун
1
Помня о том, что изо дня в день, учитывая ежедневные данные за 2 года, у нас должен быть очень и очень похожий PCA.
Томас Браун
Я думаю, причина вашей проблемы в том, что эта идея не имеет смысла. У меня нет другого решения, кроме как искать что-то другое, что может достичь ваших целей (не знаю, каковы они есть) и разумно.
Майкл Р. Черник
EUR -0.2 ZAR +0.8 USD +0.41и EUR +0.21 ZAR -0.79 USD -0.4 это очень и очень похожи. Вы просто инвертируете знак в любом из двух результатов.
ttnphns

Ответы:

22

Всякий раз, когда сюжет прыгает слишком сильно, поменяйте ориентацию. Один из эффективных критериев заключается в следующем: вычислить общее количество переходов по всем компонентам. Вычислите общее количество прыжков, если следующий собственный вектор отрицается. Если последний меньше, отрицание следующего собственного вектора.

Вот реализация. (Я не знаком с zoo, что может позволить более элегантное решение.)

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

В качестве примера, давайте запустим случайное блуждание в ортогональной группе и немного дрожим для интереса:

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

Вот скользящий PCA:

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

оригинал

Теперь исправлена ​​версия:

plot(amend(result))

Измененный

Whuber
источник
tivi+1i+1vii11vя+1, Ваш алгоритм кажется немного другим. Будет ли это работать так же?
говорит амеба: восстанови Монику
@amoeba Хотя я не совсем уверен, что именно вы делаете, это звучит как некоторые из идей, обсуждаемых в ответе Дэвида Дж. Харриса и комментариях после него. См., В частности, мой комментарий по адресу stats.stackexchange.com/questions/34396/… .
whuber
2
@ Art, насколько я понимаю, вы хотите зафиксировать знак компонента на основе некоторых внешних (внешних по отношению к PCA) предпочтений. Это хорошо, но именно так вы должны подходить к этому. Сначала сделайте скользящую PCA, убедившись, что знаки совпадают. А затем решите, основываясь на некоторых дополнительных критериях, переворачивать весь компонент или нет. Например, вы можете соотнести его с трендом евро, а если корреляция отрицательная, переверните компонент. Или что-то типа того. Это полностью зависит от вашего конкретного приложения и от вашей области знаний.
говорит амеба: восстанови Монику
1
Я согласен с интерпретацией и рекомендацией @ amoeba.
whuber
1
@amoeba: да, вы правы в этом, хотя я наивно думал, что может быть какое-то общее решение, которое не зависит от конкретного временного ряда, что-то вроде «реальной ориентации вектора» :) в любом случае, спасибо за помощь и предложения
Аноним
8

@whuber прав в том, что нет ориентации, присущей данным, но вы все равно можете убедиться, что ваши собственные векторы имеют положительную корреляцию с некоторым опорным вектором.

Например, вы можете сделать нагрузки для USD положительными на всех ваших собственных векторах (т. Е. Если загрузка в USD отрицательна, переверните знаки всего вектора). Общее направление вашего вектора все еще произвольно (так как вы могли бы вместо этого использовать EUR или ZAR в качестве ориентира), но первые несколько осей вашего PCA, вероятно, не будут перепрыгивать почти столько же - особенно потому, что ваши скользящие окна так длинная.

Дэвид Дж. Харрис
источник
7
Хорошая идея. Я попробовал это первым (вероятно, когда вы публиковали этот ответ :-). Проблема в том, что другие нагрузки могут прыгать. Чтобы исправить это, основывайте выбор знака на наибольшей загрузке. Все еще нет игры в кости: нагрузки все еще могут прыгать. Хитрость заключается в том, чтобы каждый раз выбирать ориентацию, которая создает наименьшее нарушение вектора нагрузок по сравнению с предыдущим временем.
whuber
4
@whuber Хорошая работа.
Дэвид Дж. Харрис
1
Правильно, знак нагрузок не имеет значения (ориентация). Что-то, что не было учтено, заключалось в том, что если вы выполняете это в разных пакетах программного обеспечения, различия между пакетами заключаются в том, что одна программа может приводить к отрицательным (положительным) признакам при определенных загрузках, тогда как другая приводит к положительным (отрицательным) признакам при одинаковых нагрузках. Таким образом, признаки окончательных результатов на графике 3-й серии выше могут быть инвертированы при использовании другого пакета. Нагрузки вектора отсчета также могут иметь изменение знака - и это решение не будет неправильным.
JoleT
@LEP: Я столкнулся с той же проблемой с инверсией, может быть, вы уже нашли решение этой проблемы - как узнать, что первый вектор правильный, и убедиться, что остальные будут выровнены с ним правильно - quant.stackexchange.com/questions / 3094 /… ?
Аноним
Пока матрица не является сингулярной и ни одно из собственных значений не равно нулю, большинство результатов алгоритма должны быть одинаковыми, за исключением изменения знака на 180 градусов, что не гарантируется.
JoleT
1

Что я сделал, так это вычислил расстояние L1 между последовательными собственными векторами. После нормализации этой матрицы я выбираю порог оценки по азимуту, например, 1, так что если в любом новом цикле изменение превышает этот порог, я переворачиваю собственный вектор, коэффициенты и нагрузки, чтобы иметь согласованность в окне прокрутки. Лично я не люблю навязывать данные знаки в некоторых корреляциях, поскольку они могут быть очень изменчивыми в зависимости от макропрограмм.

Рауль Муньос
источник