R中的不一致数组

时间:2014-07-23 05:51:59

标签: r

y <- matrix(c(7, 9, -5, 0, 2, 6), ncol = 1)
try <- t(y)
tryy <- try %*% y
i <- solve(tryy)
h <- y %*% i %*% try

uniroot(as.vector(solve(((1-x) * diag(6)) + h)), c(-Inf, Inf))

Error in (1 - x) * diag(6) : non-conformable arrays

此命令uniroot(as.vector(solve(((1-x) * diag(6)) + h)), c(-Inf, Inf))的目的是解决特征方程det [(1-λ)I + h] = 0

其中,λ=特征值,I =单位矩阵,h =帽子矩阵= y(y'y)^( - 1)y'

这里λ是未知的,我们必须解决它。

我不明白这里的问题在哪里?我试过了:

  as.vector(solve(6*diag(6)+h))

这不是不符合要求的。但为什么不在uniroot功能内部工作呢?

1 个答案:

答案 0 :(得分:2)

你的问题有点令人困惑,所以我必须做出一些假设。如果你想要h的特征值,那么特征方程是:

  

det(h - I *λ)= 0

  

det [(1-λ)I + h] = 0

所以我使用了前者。

鉴于上述情况,简短的回答是:这样做。

f <- function(lambda) det(h -lambda*diag(6))
F <- Vectorize(f)                         
library(rootSolve)
uniroot.all(F,c(-1000,1000),n=2000)
# [1] 0 1

# or, much more simply
eigen(h)$values
# [1]  1.000000e+00  2.220446e-16  0.000000e+00 -2.731318e-18 -6.876381e-18 -7.365903e-17

因此h有2个特征值,0和1.请注意,内置函数eigen(...)找到6个根,但其中5个在机器容差范围内。

关于代码失败原因的问题涉及更多。

首先,您的代码:

tryy <- try %*% y

是y与其自身的点积(因此,标量),作为具有一个元素的矩阵返回。当您使用solve(...)

“反转”时
i <- solve(tryy)

你只需要取倒数,所以i也是一个包含1个元素的矩阵。我不确定这是不是你的想法。

其次,uniroot(...)不起作用。第一个参数必须是函数;你传递了一个依赖于x的表达式,而f <- function(x) det(h-x*diag(6)) uniroot(f,c(-Inf,Inf)) 又是未定义的。你可以尝试:

uniroot(...)

但这不起作用,因为(a)f(...)在有限区间内工作,(b)它要求函数uniroot.all(...)在区间的末尾有不同的符号,并且( c)无论如何它只返回一个根(较小的一个)。

因此,您可以在包rootSolve中使用uniroot.all(...)lambda也需要一个函数作为它的第一个参数,但是有一个转折点:函数必须是“矢量化的”。这意味着如果传递f(...)值的向量,F <- Vectorize(f). 应返回相同长度的向量。幸运的是,在R中有一种“向量化”给定函数的简单方法,如:

uniroot.all(...)

即使这样也有限制。 eigen(...)也需要一个有限的区间,所以我们必须猜测它是什么,并且它还在n个子区间上评估F.因此,如果您的间隔不包含所有根,或者子间隔不够小,您将找不到所有根。

使用内置的{{1}}功能绝对是最佳选择。