I am working on an ordination package using ggplot2
. Right now I am constructing biplots in the traditional way, with loadings being represented with arrows. I would also be interested though to use calibrated axes and represent the loading axes as lines through the origin, and with loading labels being shown outside the plot region. In base R this is implemented in
library(OpenRepGrid)
biplot2d(boeker)
but I am looking for a ggplot2
solution. Would anybody have any thoughts how to achieve something like this in ggplot2
? Adding the variable names outside the plot region could be done like here I suppose, but how could the line segments outside the plot region be plotted?
Currently what I have is
install.packages("devtools")
library(devtools)
install_github("fawda123/ggord")
library(ggord)
data(iris)
ord <- prcomp(iris[,1:4],scale=TRUE)
ggord(ord, iris$Species)
The loadings are in ord$rotation
PC1 PC2 PC3 PC4
Sepal.Length 0.5210659 -0.37741762 0.7195664 0.2612863
Sepal.Width -0.2693474 -0.92329566 -0.2443818 -0.1235096
Petal.Length 0.5804131 -0.02449161 -0.1421264 -0.8014492
Petal.Width 0.5648565 -0.06694199 -0.6342727 0.5235971
How could I add the lines through the origin, the outside ticks and the labels outside the axis region (plossibly including the cool jittering that is applied above for overlapping labels)?
NB I do not want to turn off clipping, since some of my plot elements could sometimes go outside the bounding box
EDIT: Someone else apparently asked a similar question before, though the question is still without an answer. It points out that to do something like this in base R (though in an ugly way) one can do e.g.
plot(-1:1, -1:1, asp = 1, type = "n", xaxt = "n", yaxt = "n", xlab = "", ylab = "")
abline(a = 0, b = -0.75)
abline(a = 0, b = 0.25)
abline(a = 0, b = 2)
mtext("V1", side = 4, at = -0.75*par("usr")[2])
mtext("V2", side = 2, at = 0.25*par("usr")[1])
mtext("V3", side = 3, at = par("usr")[4]/2)
Minimal workable example in ggplot2
would be
library(ggplot2)
df <- data.frame(x = -1:1, y = -1:1)
dfLabs <- data.frame(x = c(1, -1, 1/2), y = c(-0.75, -0.25, 1), labels = paste0("V", 1:3))
p <- ggplot(data = df, aes(x = x, y = y)) + geom_blank() +
geom_abline(intercept = rep(0, 3), slope = c(-0.75, 0.25, 2)) +
theme_bw() + coord_cartesian(xlim = c(-1, 1), ylim = c(-1, 1)) +
theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(),
panel.grid = element_blank())
p + geom_text(data = dfLabs, mapping = aes(label = labels))
but as you can see no luck with the labels, and I am looking for a solution that does not require one to turn off clipping.
EDIT2: bit of a related question is how I could add custom breaks/tick marks and labels, say in red, at the top of the X axis and right of the Y axis, to show the coordinate system of the factor loadings? (in case I would scale it relative to the factor scores to make the arrows clearer, typically combined with a unit circle)
geom_path()
to get your lines? and then also use custom axes? See here for tips on that. However, Hadley doesn't like multiple plots on top of each other so you might not able to make what you want easily (see Hadley's answer here). – Richard Ericksongeom_text
, but that doesn't seem to do what you want. The question is if it is good enough? – Richard Erickson