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功能内部工作呢?
答案 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}}功能绝对是最佳选择。