简体   繁体   中英

persp plot of eigenvalues for different parameter values in R - dims do not match the length of object

I am a beginner in R thus my question may sound stupid. I have a three dimensional matrix that depends on two parameters (a and b) and I need to understand how its eigenvalues change with different values of such parameters. Basically I would like to use persp to plot the three eigenvalues (lambda1, lambda2, lambda3) in order to understand when they are positive and when they are negative.

The matrix is:

 a    b   a-b
a+b   b    a  
 a    a    b  

where -1< a <1 and -1< b <1. My idea was to do something like this:

a <- seq(-1,1,0.01)
b <- seq(-1,1,0.01)

lambda1 <- function(a,b){eigen(matrix(c(a,b,a-b,a+b,b,a,a,a,b),3,3,byrow=T))$values[[1]]} 

C <- outer(a,b,lambda1) 
nrC <- nrow(C)
ncC <- ncol(C)
Cfacet <- C[-1, -1] + C[-1, -ncC] + C[-nrC, -1] + C[-nrC, -ncC]

persp(a,b, C,col=ifelse(Cfacet>0,"red","white"))

and then proceed in the same way to obtain a perspective plot of lambda2 and lambda3. The code however does not work, and R returns the following error message:

dims [product 40401] do not match the length of object [1]

I think I understand where the problem is (not sure though), but I cannot figure out how to obtain what I am looking for. Any help or advice?

Is this what you're after:

require(akima) # akima package for easy surface interpolation
a <- seq(-1,1,0.01)
b <- seq(-1,1,0.01)
lambda1 <- function(a,b){eigen(matrix(c(a,b,a-b,a+b,b,a,a,a,b),3,3,byrow=T))$values[[1]]} 
# make it a data frame for all permutations to fix the issue that
# your current code runs for a, b vectors so you get the same result 200x
mytab<-data.frame(expand.grid(a=a,b=b))
# use adply and transform to generate the 1st eigenvalues for each
# takes a while for 200 x 200! you could reduce a & b
mytab<-mytab<-adply(mytab, 1, transform, c = lambda1(a, b))
# use interp from akima to create 40x40 matrix - you can change this
surface<-interp(mytab$a,mytab$b,mytab$c)
# plot the surface
persp(surface$x,surface$y,surface$z,col=ifelse(surface$z>=0,"red","white"))

# you can also create a spinning plot like this:

require(rgl)
plot3d(1,1,3,       # just an easy way to set the plot area
   xlab="a",
   ylab="b",
   zlab="lambda1")

surface3d(surface$x,surface$y,surface$z,
      col=ifelse(surface$z>=0,"red","white"), size=1)

EDIT - AS REQUESTED WITHOUT AKIMA AND PLYR DEPENDENCIES

a <- seq(-1,1,0.05)
b <- seq(-1,1,0.05)
lambda1 <- function(a,b){eigen(matrix(c(a,b,a-b,a+b,b,a,a,a,b),3,3,byrow=T))$values[[1]]} 
mytab<-data.frame(expand.grid(a=a,b=b))

mytab$c<-apply(mytab, 1, function(x)lambda1(x["a"],x["b"]))

surface<-NULL
surface$x<-unique(mytab$a)
surface$y<-unique(mytab$b)
surface$z<-matrix(mytab$c,nrow=length(surface$x),byrow=TRUE) 

persp(surface$x,surface$y,surface$z,col=ifelse(surface$z>=0,"red","white"))   

在此处输入图片说明

在此处输入图片说明

It looks like outer() is interpreting lambda1 as a function argument. My advice would be to try something like

C <- lambda1(outer(a,b))

I found I got the same error you did even when I tried

C <- outer(a,b, FUN = lambda1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM