DaveX
DaveX

Reputation: 745

How to get a list of eigenvectors in R

When I do the below code on my data, since there are 35 variables the resulting plot is almost useless because of all the overlap. I can't seem to find anywhere that would give me the list of data that's used to make the plot. For instance, I have a factor called avg_sour that has a direction of about 272 degrees and a magnitude of 1. That's one of the few I can actually see. If I had this data in a table, however, I could see clearly what I'm looking for without having to zoom in and out every time. Add to that the fact that this is for a presentation, so I need to be able to make this visible quickly, without them looking at multiple things--but I think I could get away with a crowded graph and a table that explained the crowded portion. Seems like it ought to be simple, but...I'm afraid I haven't found it yet. Any ideas? I can use any package I can find.

ggbiplot(xD4PCA,obs.scale = .1, var.scale = 1, 
     varname.size = 3, labels.size=6, circle = T, alpha = 0, center = T)+
     scale_x_continuous(limits=c(-2,2)) +
     scale_y_continuous(limits=c(-2,2))

enter image description here

Upvotes: 1

Views: 239

Answers (1)

Kra.P
Kra.P

Reputation: 15153

If your xD4PCA is from prcomp function, then $rotation gives you eigenvectors. See prcomp function - Value.

You may manually choose and add arrows from xD4PCA$rotation[,1:2]

I was working on this with sample data ir.pca, which is just simple prcomp object using iris data, and all these jobs are based on source code of ggbiplot.

pcobj <- ir.pca # change here with your prcomp object
nobs.factor <- sqrt(nrow(pcobj$x) - 1)
d <- pcobj$sdev
u <- sweep(pcobj$x, 2, 1 / (d * nobs.factor), FUN = '*')
v <- pcobj$rotation


choices = 1:2
choices <- pmin(choices, ncol(u))
df.u <- as.data.frame(sweep(u[,choices], 2, d[choices]^obs.scale, FUN='*'))
v <- sweep(v, 2, d^1, FUN='*')
df.v <- as.data.frame(v[, choices])
names(df.u) <- c('xvar', 'yvar')
names(df.v) <- names(df.u)
df.u <- df.u * nobs.factor
r <- sqrt(qchisq(circle.prob, df = 2)) * prod(colMeans(df.u^2))^(1/4)
v.scale <- rowSums(v^2)
df.v <- r * df.v / sqrt(max(v.scale))
df.v$varname <- rownames(v)
df.v$angle <- with(df.v, (180/pi) * atan(yvar / xvar))
df.v$hjust = with(df.v, (1 - 1.5 * sign(xvar)) / 2)
theta <- c(seq(-pi, pi, length = 50), seq(pi, -pi, length = 50))
circle <- data.frame(xvar = r * cos(theta), yvar = r * sin(theta))
df.v <- df.v[1:2,] # change here like df.v[1:2,]

ggbiplot::ggbiplot(ir.pca,obs.scale = .1, var.scale = 1, 
                   varname.size = 3, labels.size=6, circle = T, alpha = 0, center = T, var.axes = FALSE)+
  scale_x_continuous(limits=c(-2,2)) +
  scale_y_continuous(limits=c(-2,2)) +
  geom_segment(data = df.v, aes(x = 0, y = 0, xend = xvar, yend = yvar),
               arrow = arrow(length = unit(1/2, 'picas')), 
               color = muted('red')) +
  geom_text(data = df.v, 
            aes(label = rownames(df.v), x = xvar, y = yvar, 
                angle = angle, hjust = hjust), 
            color = 'darkred', size = 3)
ggbiplot::ggbiplot(ir.pca)+
  scale_x_continuous(limits=c(-2,2)) +
  scale_y_continuous(limits=c(-2,2)) + 
  geom_path(data = circle, color = muted('white'), 
            size = 1/2, alpha = 1/3)

Original one(having all four variables)

enter image description here

Edited one(select only first two variables)

enter image description here

Upvotes: 2

Related Questions