M. Beausoleil
M. Beausoleil

Reputation: 3555

Figure labels: add text on graphs in the same location despite figure size

I want to know how it's possible to add a letter to reference a graph in R, but without always changing the y and x value. I want the text to be always at the same place (on the same baseline, and at the same relative distance on the x axis.

set.seed(1234)
plot(2,3)
text(x = 1.5,y = 4, "A", font = 2 )
plot(rnorm(100))
text(x = 1.5,y = 2, "B", font = 2)

As you can see, the letter B is not at the same distance on the x axis and it's a little down. I would like this to be adjusting automatically when I resize the graphic window in RStudio. enter image description here

Upvotes: 3

Views: 1763

Answers (4)

koekenbakker
koekenbakker

Reputation: 3604

Another option is to use mtext with with left justification and xpd=NA:

set.seed(1234)
layout(mat=matrix(c(1,2,3,3,4,4,4,4), ncol=4))

plot(rnorm(100))
mtext(text=LETTERS[1], xpd=NA, side=3, adj=0, font=2)

plot(rnorm(100))    
mtext(text=LETTERS[2], xpd=NA, side=3, adj=0, font=2)

plot(rnorm(100))
mtext(text=LETTERS[3], xpd=NA, side=3, adj=0, font=2)

plot(rnorm(100))
mtext(text=LETTERS[4], xpd=NA, side=3, adj=0, font=2)

Upvotes: 0

R. Schifini
R. Schifini

Reputation: 9313

You just need to get the y axis limits with par("usr") and then set the text accordingly:

set.seed(1234)

# Define the y value where the text is to be placed on the first graph
textY = 2

# Plot the graph, text and get the axis limits
plot(2,3)
text(x = 1.5,y = textY, "A", font = 2 )
yA = par("usr")

#Plot the second graph and get the axis limits    
plot(rnorm(100))
yB = par("usr")

# Calculate the y value where to place the text on the second graph
new_yB = (textY-yA[3])/(yA[4]-yA[3])*(yB[4]-yB[3])+yB[3]
text(x = 1.5,y = new_yB, "B", font = 2)

par("usr") will return a vector that contains 4 numbers: xLow, xHigh, yLow, yHigh

Upvotes: 1

m-dz
m-dz

Reputation: 2362

You can use cowplot::plot_grid function:

https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html

enter image description here

Example:

require(cowplot)
require(ggplot2)

set.seed(1234)

# Create plot "template" with some dummy data
gg <- ggplot(data = data.frame(1,2), aes(x = X, y = Y)) +
  theme_light() +
  theme(plot.margin = unit(c(10.5, 10.5, 5.5, 5.5), "points"))

# Create the actual plots
gg1 <- gg + geom_point(data = data.frame(X = 2, Y = 3))
gg2 <- gg + geom_point(data = data.frame(X = rnorm(100), Y = rnorm(100)))

plot_grid(gg1, gg2, labels = c("A", "B"))

Upvotes: 2

dayne
dayne

Reputation: 7784

This is how I have solved that problem in the past (based on these questions: Get margin line locations (mgp) in user coordinates, Get margin line locations in log space):

line2user <- function(line, side) {
  lh <- par('cin')[2] * par('cex') * par('lheight')
  x_off <- diff(grconvertX(c(0, lh), 'inches', 'npc'))
  y_off <- diff(grconvertY(c(0, lh), 'inches', 'npc'))
  switch(side,
         `1` = grconvertY(-line * y_off, 'npc', 'user'),
         `2` = grconvertX(-line * x_off, 'npc', 'user'),
         `3` = grconvertY(1 + line * y_off, 'npc', 'user'),
         `4` = grconvertX(1 + line * x_off, 'npc', 'user'),
         stop("Side must be 1, 2, 3, or 4", call.=FALSE))
}

addfiglab <- function(lab, xl = par()$mar[2], yl = par()$mar[3]) {

  text(x = line2user(xl, 2), y = line2user(yl, 3), 
       lab, xpd = NA, font = 2, cex = 1.5, adj = c(0, 1))

}

par(mfrow = c(1, 2))
plot(0)
addfiglab("A")
plot(1000)
addfiglab("B")

enter image description here

Upvotes: 4

Related Questions