eigen {base} | R Documentation

## Spectral Decomposition of a Matrix

### Description

This function computes eigenvalues and eigenvectors by providing an interface to the EISPACK routines `RS`, `RG`, `CH` and `CG`.

### Usage

    eigen(x, symmetric, only.values=FALSE)

### Arguments

`x` | a matrix whose spectral decomposition is to be computed.
`symmetric` | if `TRUE`, the matrix is assumed to be symmetric (or Hermitian if complex) and only its lower triangle is used. If `symmetric` is not specified, the matrix is inspected for symmetry.
`only.values` | if `TRUE`, only the eigenvalues are computed and returned, otherwise both eigenvalues and eigenvectors are returned.

### Value

The spectral decomposition of `x` is returned as components of a list.

`values` | a vector containing the p eigenvalues of `x`, sorted in decreasing order, according to `Mod(values)` if they are complex.
`vectors` | a p * p matrix whose columns contain the eigenvectors of `x`, or `NULL` if `only.values` is `TRUE`.

### References

Smith, B. T, Boyle, J. M., Dongarra, J. J., Garbow, B. S., Ikebe,Y., Klema, V., and Moler, C. B. (1976). Matrix Eigensystems Routines – EISPACK Guide. Springer-Verlag Lecture Notes in Computer Science.

### See Also

`svd`, a generalization of `eigen`; `qr`, and `chol` for related decompositions.

To compute the determinant of a matrix, the `qr` decomposition is much more efficient: `det`.

### Examples

    eigen(cbind(c(1,-1),c(-1,1)))
    eigen(cbind(c(1,-1),c(-1,1)), symmetric = FALSE)# same (different algorithm).

    eigen(cbind(1,c(1,-1)), only.values = TRUE)
    eigen(cbind(-1,2:1)) # complex values
    eigen(print(cbind(c(0,1i), c(-1i,0))))# Hermite ==> real Eigen values
    ## 3 x 3:
    eigen(cbind( 1,3:1,1:3))
    eigen(cbind(-1,c(1:2,0),0:2)) # complex values

    Meps <- .Alias(.Machine$double.eps)
    m <- matrix(round(rnorm(25),3), 5,5)
    sm <- m + t(m) #- symmetric matrix
    em <- eigen(sm); V <- em$vect
    print(lam <- em$values) # ordered DEcreasingly

    stopifnot(
     abs(sm %*% V - V %*% diag(lam))          < 60*Meps,
     abs(sm       - V %*% diag(lam) %*% t(V)) < 60*Meps)

    ##------- Symmetric = FALSE:  -- different to above : ---

    em <- eigen(sm, symmetric = FALSE); V2 <- em$vect
    print(lam2 <- em$values) # ordered decreasingly in ABSolute value !
                             # and V2 is not normalized (where V is):
    print(i <- rev(order(lam2)))
    stopifnot(abs(1 - lam2[i] / lam) < 60 * Meps)

    zapsmall(Diag <- t(V2) %*% V2) # orthogonal, but not normalized
    print(norm2V <- apply(V2 * V2, 2, sum))
    stopifnot( abs(1- norm2V / diag(Diag)) < 60*Meps)

    V2n <- sweep(V2,2, STATS= sqrt(norm2V), FUN="/")## V2n are now Normalized EV
    apply(V2n * V2n, 2, sum)
    ##[1] 1 1 1 1 1

    ## Both are now TRUE:
    stopifnot(abs(sm %*% V2n - V2n %*% diag(lam2))            < 60*Meps,
              abs(sm         - V2n %*% diag(lam2) %*% t(V2n)) < 60*Meps)

    ## Re-ordered as with symmetric:
    sV <- V2n[,i]
    slam <- lam2[i]
    all(abs(sm %*% sV -  sV %*% diag(slam))             < 60*Meps)
    all(abs(sm        -  sV %*% diag(slam) %*% t(sV)) < 60*Meps)
    ## sV  *is* now equal to V  -- up to sign (+-) and rounding errors
    all(abs(c(1 - abs(sV / V)))       <     1000*Meps) # TRUE (P ~ 0.95)

[Package Contents]