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.