Problem
I'm having trouble plotting with ggplot the principal components as vectors projected on the plane given by two of the original variables in my dataset, together with the observations. As far as I can tell, the problem does not depend on the dataset, I've tried this with a few, but df below is the Body Measurements Dataset in Kaggle, excluding the first two columns.
Code
I have a working script for the reciprocal problem: plotting the original variables in the plane given by the first two principal components, replicating in ggplot the output of biplot(). I do the singular value decomposition manually. The code for this is the following.
x <- df %>% as.matrix() %>% scale()
matrices <- svd(x)
# get the coords of the obvs wrt the PCs
df.pc <- matrices$u %*% diag(matrices$d) %>% as.data.frame()
df.pc$Labels <- rownames(df)
# get the coords of the original variables wrt to the PCs
old.basis <- sqrt(diag(matrices$d)) %*% matrices$v %>% as.data.frame()
old.basis$Names <- names(df)
ggplot(df.pc, aes(x = V1, y =V2, label= Names)) +
theme(aspect.ratio = 1) +
geom_text() +
geom_segment(data = old.basis, aes(x = 0, y = 0, xend = V1, yend = V2),
arrow = arrow(length = unit(0.1, 'inches')), color = 'orange') +
geom_text(data = old.basis, aes(label = Names), color = 'orange')
This works like a charm. I tried the same approach to produce the plot I previously said.
# get the coords of the PCs wrt to the original variables
new.basis <- t(sqrt(diag(matrices$d)) %*% matrices$v) %>% as.data.frame()
names(new.basis) <- names(df)
new.basis$Names <- names(old.basis[,1:11]) # last column is Names
ggplot(df, aes(x = Y1, y = Y2, label = row.names(df)) ) +
theme(aspect.ratio = 1) +
geom_text() +
geom_segment(data = new.basis, aes(x = 0, y = 0, xend = Y1, yend = Y2),
arrow = arrow(length = unit(0.1, 'inches')), color = 'orange') +
geom_text(data = new.basis, aes(label = Names), color = 'orange')
here Y1 and Y2 are the names I gave to the first two variables in df. But...
The error I get
...I get the following error every time.
Error in `check_aesthetics()`:
! Aesthetics must be either length 1 or the same as the data (11): label
Run `rlang::last_error()` to see where the error occurred.
