2012-09-06 22 views
6

Estoy tratando de verificar si mi matriz es singular usando el enfoque de valores propios (es decir, si uno de los valores propios es cero, entonces la matriz es singular). Aquí está el código:utilizando valores propios para comprobar la singularidad: identificar columnas colineales

z <- matrix(c(-3,2,1,4,-9,6,3,12,5,5,9,4),nrow=4,ncol=3) 
eigen(t(z)%*%z)$values 

Sé que los autovalores están ordenados en orden descendente. ¿Puede alguien decirme por favor si hay una manera de descubrir qué valor propio se asocia a qué columna en la matriz? Necesito eliminar las columnas colineales.

Puede ser obvio en el ejemplo anterior, pero es solo un ejemplo destinado a ahorrarle tiempo al crear una nueva matriz.

+1

'eigen' no funciona para una matriz no cuadrada –

+0

Se necesita una matriz cuadrada para calcular los valores propios ... – James

+0

creo que quería decir? 'z <- matrix (c (-3,2,1,4, -9,6,3,12,5,5,9,4), nrow = 4, ncol = 4) eigen (z) $ values ' –

Respuesta

7

Ejemplo:

z <- matrix(c(-3,2,1,4,-9,6,3,12,5,5,9,4),nrow=4,ncol=3) 
m <- crossprod(z) ## slightly more efficient than t(z) %*% z 

Esto le indica que el tercer vector propio correspondiente a las combinaciones colineales:

ee <- eigen(m) 
(evals <- zapsmall(ee$values)) 
## [1] 322.7585 124.2415 0.0000 

Ahora examine los vectores propios correspondientes, que se enumeran como columnas correspondientes a sus respectivos valores propios:

(evecs <- zapsmall(ee$vectors)) 
    ## [1,] -0.2975496 -0.1070713 0.9486833 
    ## [2,] -0.8926487 -0.3212138 -0.3162278 
    ## [3,] -0.3385891 0.9409343 0.0000000 

El tercer valor propio es cero; los primeros dos elementos del tercer vector propio (evecs[,3]) son distintos de cero, lo que indica que las columnas 1 y 2 son colineales.

Aquí está una manera de automatizar esta prueba:

testcols <- function(ee) { 
     ## split eigenvector matrix into a list, by columns 
     evecs <- split(zapsmall(ee$vectors),col(ee$vectors)) 
     ## for non-zero eigenvalues, list non-zero evec components 
     mapply(function(val,vec) { 
      if (val!=0) NULL else which(vec!=0) 
     },zapsmall(ee$values),evecs) 
    } 

testcols(ee) 
## [[1]] 
## NULL 
## [[2]] 
## NULL 
## [[3]] 
## [1] 1 2 
+0

@BenBolker, entonces, ¿qué columnas en z son colineales? o tiene evals = 0 –

+2

una columna no tiene un autovalor de cero, por definición: es una * combinación lineal * de columnas que son colineales - columnas 1 y 2 en su ejemplo. –

+0

Para aquellos interesados, aquí hay un enlace a una publicación de SO que hice, implementando esencialmente este mismo método (específicamente para el contexto de análisis de regresión) pero en el lenguaje Julia, y dando un poco más de fondo matemático: http: // stackoverflow. com/questions/39082724/perfect-or-near-multicollinearity-in-julia/39082831 # 39082831 –

2

Se puede utilizar para hacer un tmp <- svd(z) SVD. Los valores propios se guardan en tmp$d como una matriz diagonal de valores propios. Esto funciona también con una matriz no cuadrada.

> diag(tmp$d) 
     [,1]  [,2]   [,3] 
[1,] 17.96548 0.00000 0.000000e+00 
[2,] 0.00000 11.14637 0.000000e+00 
[3,] 0.00000 0.00000 8.787239e-16 
Cuestiones relacionadas