Stat - 1 year ago 60

R Question

I am not sure what I am doing wrong here.

`ee <- eigen(crossprod(X))$values`

for(i in 1:length(ee)){

if(ee[i]==0:1e^-9) stop("singular Matrix")}

Using the eigen value approach, I am trying to determine if the matrix is singular or not. I am attempting to find out if one of the eigen values of the matrix is between 0 and 10^-9. How can I use the if statement (as above) correctly to achieve my goal? Is there any other way to approach this?

what if I want to concatenate the zero eigen value in vector

`zer <-NULL`

ee <- eigen(crossprod(X))$values

for(i in 1:length(ee)){

if(abs(ee[i])<=1e-9)zer <- c(zer,ee[i])}

Can I do that?

Answer Source

@AriBFriedman is quite correct. I can, however see a couple of other issues

`1e^-9`

should be`1e-9`

.`0:1e-9`

returns`0`

, (`:`

creates a sequence by one between 0 and 1e-9, therefore returns just`0`

. See`?`:``

for more details- Using
`==`

with decimals will cause problems due to floating point arithmetic

In the form written, your code checks (individually) whether the elements `ee[i] == 0`

, which is not what you want (nor does it make sense in terms floating point arithmetic)

You are looking for cases where the eigen value is less than this small number, so use less than (`<`

).

What you are looking for is something like

```
if(any(abs(ee) < 1e-9)) stop('singular matrix')
```

If you want to get the `0`

(or small) eigen vectors, then use `which`

```
# this will give the indexs (which elements are small)
small_values <- which(abs(ee) < 1e-9))
# and those small values
ee[small_values]
```

There is no need for the `for`

loop as everything being done is vectorized.