【问题标题】:A function for calculating the eigenvalues of a matrix in R用于计算 R 中矩阵的特征值的函数
【发布时间】:2013-04-21 14:09:08
【问题描述】:

我想编写一个类似eigen() 的函数来计算任意矩阵的特征值和特征向量。我写了以下代码来计算特征值,我需要一个函数或方法来求解得到的线性方程。

eig <- function(x){
       if(nrow(x)!=ncol(x)) stop("dimension error")
          ff <- function(lambda){
                for(i in 1:nrow(x)) x[i,i] <- x[i,i] - lambda
                }
det(x)
}

我需要求解det(x)=0,这是一个多项式线性方程,以找到lambda 的值。有什么办法吗?

【问题讨论】:

  • 试试optim函数。
  • uniroot 找到根?
  • 但是optim() 找到了最小化函数的根。我想解决它,比如polyroot()
  • 你用谷歌搜索过“[r] 非线性根查找”...?
  • 我要写我的函数!不使用eigen()!

标签: r eigenvector eigenvalue linear-equation


【解决方案1】:

这是使用uniroot.all 的一种解决方案:

library(rootSolve)
myeig <- function(mat){
  myeig1 <- function(lambda) {
    y = mat
    diag(y) = diag(mat) - lambda
    return(det(y))
  }

  myeig2 <- function(lambda){
    sapply(lambda, myeig1)
  }
  uniroot.all(myeig2, c(-10, 10))
}

R > x <- matrix(rnorm(9), 3)
R > eigen(x)$values
[1] -1.77461906 -1.21589769 -0.01010515
R > myeig(x)
[1] -1.77462211 -1.21589767 -0.01009019

【讨论】:

  • 你有合适的工具,但你能写一个myeig 函数,它只接受一个矩阵作为输入并返回特征值吗?
  • 感谢您的建议。我总结并更新了我的答案。
  • 谢谢 liuminzhao。为了确定特征向量,我应该为每个特征值求解另一个线性方程组。这是我在您的帮助下编写的代码:for(i in 1:nrow(mat)){ solve(mat-values[i]*diag(nrow(mat)),rep(0,nrow(mat)))} 但这只会返回不是特征向量的零向量。我怎样才能找到这个答案?
  • uniroot.all() 可以在上面的例子中找到myeig2 的复根吗?如果没有,哪个函数可以做到这一点?
  • @Mahmood 我认为它做不到。 polyroot 可以求复根,但我认为你需要先得到多项式系数。
【解决方案2】:

计算行列式是个坏主意,因为它在数值上不稳定。即使对于中等大小的矩阵,您也可以轻松获得Inf 等。我建议阅读以下答案(阅读它们,否则你不知道我的代码在做什么):

然后使用以下任一方法

NullSpace(A - diag(lambda, nrow(A)))
nullspace(A - diag(lambda, nrow(A)))

【讨论】:

    【解决方案3】:

    如果有两个重复的特征值,@liuminzhao 的解决方案将不起作用。该函数将无法找到根,因为矩阵的特征多项式不会改变符号(它是零并且不会越过零线),这就是rootSolve::uniroot.all()在寻找根时所做的。所以你需要另一种方法来找到一个局部最小值(比如optim())。而且,它会无法确定重复特征值的个数。

    更好的方法是找到特征方程,这很容易用pracma::charpoly() 完成,然后使用polyroot()

    par <- pracma::charpoly(M) # find parameters of the CP of matrix M
    par <- par[length(par):1]  # reverse order for polyroot()
    roots <- Re(polyroot(par)) # keep real part of the polyroot()
    

    pracma::charpoly() 本身并不太复杂,参见其源代码code,从a1 &lt;- a 行开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2010-10-17
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多