我在R上的rollapply PCA中收到“跳跃”加载。可以修复它吗?


20

我有10年的28种不同货币的每日收益数据。我希望提取第一个主要成分,而不是希望在整个10年中都使用PCA,而是希望应用2年的窗口,因为货币的行为会发生变化,因此我想对此进行反映。但是,我有一个主要问题,那就是princomp()和prcomp()函数在相邻的PCA分析中(即相隔1天)经常会从正加载跳跃到负加载。查看欧元货币的加载图:

在此处输入图片说明

显然,我不能使用它,因为相邻的载荷会从正数跳到负数,所以我的使用它们的系列将是错误的。现在看一下欧元货币加载的绝对值:

在此处输入图片说明

问题当然是我仍然不能使用它,因为从上图可以看出,负载确实会从负向正移动,有时会反过来,这是我需要保留的特征。

有什么办法可以解决这个问题?我可以强制特征向量方向在相邻的PCA中始终相同吗?

顺便说一句,FactoMineR PCA()函数也会出现此问题。rollapply的代码在这里:

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

3
您能解释特征向量“方向”的意思吗?据我所知,没有数据固有的东西(这就是为什么不同的软件会产生不同的归一化特征向量的原因之一。)这听起来像是您要的是不存在且毫无意义的东西。
ub

1
好吧,有一天我会这样加载:EUR -0.2 ZAR +0.8 USD +0.41 ..... 28种货币。第二天,我将得到EUR +0.21 ZAR -0.79 USD -0.4等。因此,PCA选择将数据旋转到的轴在第二天的方向与第一天的方向完全相反。这些负载跳跃,我希望以某种方式避免它。我了解PCA代码并不真正关心轴的方向,只要它在一天之内的所有负载中保持一致即可,但是我需要在多天内保持一致。
托马斯·布朗

1
请记住,考虑到每天的数据滚动两年,从一天到第二天,我们应该有非常非常相似的PCA。
托马斯·布朗

我认为您遇到问题的原因是,这种可套用的想法没有任何意义。除了寻找可以实现您的目标(不确定目标是什么)并且明智的其他方法外,我别无选择。
Michael R. Chernick

EUR -0.2 ZAR +0.8 USD +0.41并且EUR +0.21 ZAR -0.79 USD -0.4 非常非常相似。您只需将两个结果中的任何一个取反即可。
ttnphns 2012年

Answers:


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

已修改


Ť一世v一世+1个一世+1个v一世一世1个-1个v一世+1个。您的算法似乎有些不同。它会以相同的方式工作吗?
变形虫说恢复莫妮卡

@amoeba尽管我不确定您到底在做什么,但这听起来像是David J. Harris的答案及其后的评论中讨论的一些想法。尤其请参见stats.stackexchange.com/questions/34396/…上的我的评论。
ub

2
@Art,据我所知,您想根据一些外部(PCA外部)首选项来修复组件的符号。很好,但这就是您应该采用的方法。首先做滑动式PCA,确保信号一致。然后,根据一些其他标准,决定是否翻转整个组件。例如,您可以将其与欧元趋势相关联,如果相关性为负,则翻转该组件。或类似的东西。这完全取决于您的特定应用程序和您的领域知识。
变形虫说莫妮卡(Monica)恢复2015年

1
我同意@amoeba的解释和建议。
ub

1
@amoeba:是的,您对此是正确的,尽管,我天真的认为可能存在一些不依赖于特定时间序列的通用解决方案,例如“矢量的真实方向” :)无论如何,谢谢您的帮助和建议
匿名2015年

8

@whuber是对的,数据没有固有的方向,但是您仍然可以强制本征向量与某个参考向量具有正相关。

例如,您可以在所有特征向量上使美元的负荷为正(即,如果美元的负荷为负,则翻转整个向量的符号)。向量的总体方向仍然是任意的(因为您可以使用EUR或ZAR作为参考),但是PCA的前几个轴可能不会跳得差不多-尤其是因为滚动窗口是如此长。


7
好主意。我首先尝试了此操作(可能是在您发布此答案时:-)。问题在于其他负载可能会跳来跳去。要解决此问题,请以最大负载为基础选择符号。仍然没有骰子:负载仍然可以跳跃。诀窍是每次都选择一个方向,该方向在上一次加载矢量中产生最小的干扰。
ub

4
@whuber很好。
David J. Harris

1
正确,加载的符号无关紧要(方向)。未解决的问题是,如果您在不同的软件包之间执行此操作,则包之间的差异是,一个程序可能在特定加载上导致负(正)号,而另一个程序在相同加载下导致正(负)号。因此,当使用其他封装时,上面3系列图中最终结果的符号可能会颠倒。参考矢量加载也可能有符号变化-这种解决方案不会是错误的。
JoleT,2014年

@LEP:我在反演时也遇到了同样的问题,也许您已经找到了解决此问题的方法-如何找出第一个向量是正确的,并确保其余向量正确对齐-quantum.stackexchange.com/questions / 3094 /…
匿名

只要矩阵不是奇异的并且特征值都不为零,则大多数算法结果应该是相同的,除了符号发生180度变化-这是不能保证的。
JoleT

1

我所做的是计算连续特征向量之间的L1距离。在对该矩阵进行归一化之后,我选择z得分阈值(例如1),以便在任何新的滚动中,如果变化高于该阈值,我将翻转特征向量,因子和载荷,以便在滚动窗口中保持一致。就个人而言,我不喜欢在某些关联中强制给定符号,因为取决于宏驱动程序,它们可能非常不稳定。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.