Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
145 views
in Technique[技术] by (71.8m points)

How to plot distance biplot and correlation biplot results of SVD/PCA in R?

I searched for a long time for a straightforward explanation of the distance vs correlation biplots, as well as an explanation of how to transform the standard outputs of PCA to achieve the two biplots. All the stack overflow explanations 1 2 3 4 I saw went way over my head with math terms. How can I create both a distance biplot and a correlation biplot using the outputs of R's prcomp?

question from:https://stackoverflow.com/questions/65943174/how-to-plot-distance-biplot-and-correlation-biplot-results-of-svd-pca-in-r

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The best explanation I found is some lecture slides from Pierre Legendre, Département de sciences biologiques, Université de Montréal (http://biol09.biol.umontreal.ca/PLcourses/Ordination_section_1.1_PCA_Eng.pdf). However, while these slides did show the way to plot a distance and correlation biplot manually, they didn't show how to plot the distance and correlation biplots from the results of prcomp.

So I worked through an example that shows how one can use the outputs of prcomp for them to be equivalent to the example walked through in the pdf above. I am leaving this here for future people like myself who are wondering how to plot a distance vs correlation biplot and when you want to use each (according to Pierre Legendre)

set.seed(1)

#Run standard PCA
pca_res <- prcomp(mtcars[, 1:7], center = TRUE, scale = TRUE, retx = TRUE)

#To print a distance biplot, simply plot pca_red$x as points and $rotation
#as vectors
library(ggplot2)

arrow_len <- 3 #arbitrary scaling of arrows so they're same mag as PC scores
ggplot(data = as.data.frame(pca_res$x), aes(x = PC1, y = PC2)) +
  geom_point() +
  geom_segment(data = as.data.frame(pca_res$rotation),
                    aes(x = 0, y = 0, yend = arrow_len*PC1, xend = arrow_len*PC2),
                    arrow = arrow(length = unit(0.02, "npc"))) +
  geom_text(data = as.data.frame(pca_res$rotation),
            mapping = aes(y = arrow_len*PC1, x = arrow_len*PC2,
                label = row.names(pca_res$rotation)))

#This is equivalent to the following steps:
Y_centered <- scale(mtcars[, 1:7], center = TRUE, scale = TRUE)
Y_eig <- eigen(cov(Y_centered)) 
#Note that Y_eig$vectors == pca_res$rotation ("rotations" or "loadings")
# and Y_eig$values (eigenvalues) == pca_res$sdev**2

#For a distance biplot
U_frame <- Y_eig$vectors
#F is your PC scores, achieved by multiplying your original data by the rotations
F_frame <- Y_centered %*% U_frame

#flipping constants if needed bc PC axis direction is arbitrary
x_flip = -1
y_flip = -1
ggplot(data = as.data.frame(F_frame), aes(x = x_flip*V1, y = y_flip*V2)) +
  geom_point() +
  geom_segment(data = as.data.frame(U_frame),
               aes(x = 0, y = 0, yend = y_flip*arrow_len*V1, xend = x_flip*arrow_len*V2),
               arrow = arrow(length = unit(0.02, "npc"))) +
  geom_text(data = as.data.frame(U_frame),
            mapping = aes(y = y_flip*arrow_len*V1, x = x_flip*arrow_len*V2,
                          label = colnames(Y_centered)))

#To print a correlation biplot, matrix multiply your rotations/loadings
# by the identity matrix times your PCA standard deviations 
# (equivalent to the sqrt of your eigen values)
U_frame_scaling2 <- U_frame %*% diag(Y_eig$values^(0.5))

#And divide your PC scores by your PCA standard deviations
# (equivalent to 1/sqrt(eigen values)
F_frame_scaling2 <- F_frame %*% diag(Y_eig$values^(-0.5))

#Plot
arrow_len <- 1.5 #arbitrary scaling of arrows so they're same mag as PC scores

ggplot(data = as.data.frame(pca_res$x %*% diag(1/pca_res$sdev)), 
       aes(x = V1, y = V2)) +
  geom_point() +
  geom_segment(data = as.data.frame(pca_res$rotation %*% diag(pca_res$sdev)),
               aes(x = 0, y = 0, yend = arrow_len*V1, xend = arrow_len*V2),
               arrow = arrow(length = unit(0.02, "npc"))) +
  geom_text(data = as.data.frame(pca_res$rotation %*% diag(pca_res$sdev)),
            mapping = aes(y = arrow_len*V1, x = arrow_len*V2,
                          label = row.names(pca_res$rotation)))

ggplot(data = as.data.frame(F_frame_scaling2), aes(x = x_flip*V1, y = y_flip*V2)) +
  geom_point() +
  geom_segment(data = as.data.frame(U_frame_scaling2),
               aes(x = 0, y = 0, yend = y_flip*arrow_len*V1, xend = x_flip*arrow_len*V2),
               arrow = arrow(length = unit(0.02, "npc"))) +
  geom_text(data = as.data.frame(U_frame_scaling2),
            mapping = aes(y = y_flip*arrow_len*V1, x = x_flip*arrow_len*V2,
                          label = colnames(Y_centered)))

As for the differences between the two (in case the pdf above becomes unavailable at some point):

Scaling type 1: distance biplot, used when the interest is on the positions of the objects with respect to one another. –

  • Plot matrices F to represent the objects and U for the variables.

Scaling type 2: correlation biplot, used when the angular relationships among the variables are of primary interest. –

  • Plot matrices G to represent the objects and Usc2 for the variables, where G = FΛ–1/2 , and Usc2 = UΛ1/2.

In scaling 1 (distance biplot),

  • the sites have variances, along each axis (or principal component), equal to the axis eigenvalue (column of F);
  • the eigenvectors (columns of U) are normed to lengths = 1;
  • the length (norm) of each species vector in the pdimensional ordination space (rows of U) is 1.

In scaling 2 (correlation biplot),

  • the sites have unit variance along each axis (columns of G);
  • the eigenvectors (columns of Usc2) are normed to lengths = sqrt(eigenvalues);
  • the norm of each species vector in the p-dimensional ordination space (rows of Usc2) is its standard deviation.

In scaling 1 (distance biplot),

  1. Distances among objects approximate their Euclidean distances in full multidimensional space.
  2. Projecting an object at right angle on a descriptor approximates the position of the object along that descriptor.
  3. Since descriptors have equal lengths of 1 in the full-dimensional space, the length of the projection of a descriptor in reduced space indicates how much it contributes to the formation of that space.
  4. A scaling 1 biplot thus shows which variables contribute the most to the ordination in a few dimensions (see also section: Equilibrium contribution of variables).
  5. The descriptor-axes are orthogonal (90°) to one another in multidimensional space. These right angles, projected in reduced space, do not reflect the variables’ correlations.

In scaling 2 (correlation biplot),

  1. Distances among objects approximate their Mahalanobis distances in full multidimensional space.
  2. Projecting an object at right angle on a descriptor approximates the position of the object along that descriptor.
  3. Since descriptors have lengths sj in full-dimensional space, the length of the projection of a descriptor j in reduced space is an approximation of its standard deviation sj . Note: sj is 1 when the variables have been standardized.
  4. The angles between descriptors in the biplot reflect their correlations.
  5. When the distance relationships among objects are important for interpretation, this type of biplot is inadequate; a distance biplot should be used.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...