Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Position ggplot text in each corner

Tags:

r

ggplot2

I've got a scatter plot with a horizontal and a vertical line, which depict thresholds values, and therefore they divide the plot into four quadrants. I'd like to label the quadrants. I think the best way to do this would be a number in each of the four corners of the graph (alternative suggestions are welcome!).

I've managed to put a text into the corner of each quadrant, but the positions are not perfect. I assume that the problem has to do with the fact that the scaling of the axes is different (the range of values is about the same, but the width of my figure is about three times the height).

Currently I proceed the following way. First I create the graph with the points and the two lines, then I build it in order to get the range of the two axes, which I use in order to adjust the position of the texts.

plot.build = ggplot_build(plot)

xpos = numeric(4)
xpos[2] = xpos[3] = plot.build$panel$ranges[[1]]$x.range[1]
xpos[1] = xpos[4] = plot.build$panel$ranges[[1]]$x.range[2]

ypos = numeric(4)
ypos[1] = ypos[2] = plot.build$panel$ranges[[1]]$y.range[2]
ypos[3] = ypos[4] = plot.build$panel$ranges[[1]]$y.range[1]


plot = plot + geom_text(aes(x2,y2,label = texthere), 
                    data.frame(x2=xpos, y2=ypos, texthere=c("1", "2", "3", "4")),
                    color="#4daf4a", size=4)

Basically this works, but due to the scaling the space between the numbers and the borders of the plot are not the same for both axes. I've tried to adjust the x position of the text, but then ggplot just expands the range of values, the positions (relative to the borders) stay the same. Is there a way to move the text without changing the range of values?

Thanks in advance!

like image 474
tho_mi Avatar asked Aug 20 '15 16:08

tho_mi


3 Answers

This example uses the Inf & -Inf values to position the text at the corners and then hjust and vjust arguments in the geom_text to position the text inside the plot. Use the hjustvar and vjustvar to position them further into or outside the plot.

As mentioned by @baptiste it's best to use a new data set for the annotations

df <- data.frame(x2=rnorm(100),y2=rnorm(100));library(ggplot2)

annotations <- data.frame(
        xpos = c(-Inf,-Inf,Inf,Inf),
        ypos =  c(-Inf, Inf,-Inf,Inf),
        annotateText = c("Bottom Left (h0,v0)","Top Left (h0,v1)"
                        ,"Bottom Right h1,v0","Top Right h1,v1"),
        hjustvar = c(0,0,1,1) ,
        vjustvar = c(0,1,0,1)) #<- adjust


  ggplot(df, aes(x2, y2)) + geom_point()+
            geom_text(data=annotations,aes(x=xpos,y=ypos,hjust=hjustvar,vjust=vjustvar,label=annotateText))

Example of Text Annotations in Corner

If we wanted to change any of the text positions, we would adjust the horizontal positions with hjustvar and the vertical positions with vjustvar.

# How To Adjust positions (away from corners)
annotations$hjustvar<-c(0,  -1.5,  1,  2.5)  # higher values = right, lower values = left 
annotations$vjustvar<-c(0,1,0,1) # higher values = up, lower values = down 

ggplot(df, aes(x2, y2)) + geom_point()+
        geom_text(data = annotations, aes(x=xpos,y=ypos,hjust=hjustvar,
                                          vjust=vjustvar,label=annotateText))

Height Adjustment away from Corners

Hope this works!

like image 94
Timo Kvamme Avatar answered Nov 10 '22 12:11

Timo Kvamme


when adding annotations, make sure to give a new data set, or to use annotate, otherwise multiple labels will be superimposed giving a jagged look. Here's a minimal change from the other answer,

df <- data.frame(x2=rnorm(100),y2=rnorm(100))
library(ggplot2)

annotations <- data.frame(
   xpos = c(-Inf,-Inf,Inf,Inf),
   ypos =  c(-Inf, Inf,-Inf,Inf),
   annotateText = c("Text","tExt","teXt","texT"),
   hjustvar = c(0,0,1,1) ,
   vjustvar = c(0,1.0,0,1))


  ggplot(df, aes(x2, y2)) + geom_point()+
  geom_text(data = annotations, aes(x=xpos,y=ypos,hjust=hjustvar,
                vjust=vjustvar,label=annotateText))

enter image description here

like image 40
baptiste Avatar answered Nov 10 '22 13:11

baptiste


Just thought I would expand on the answers given and produce something that looks a little more aesthetically pleasing. At first, the direction that text moves when using hjust and vjust might seem a bit counter-intuitive (at least to me), so I've commented each line to help others understand.

library(tidyverse)

##Example 1
annotations1 <- data.frame(
  xpos = c(-Inf, -Inf, Inf, Inf), ypos =  c(-Inf, Inf, -Inf, Inf), #left-bottom, left-top, right-bottom, right-top
  annotateText = c("Text", "tExt", "teXt", "texT"),
  # hjustvar = c(0,0,1,1), vjustvar = c(0,1,0,1))   #original placement in each corner
  hjustvar = c(-.5,   #shifts bottom left 'Text' to the right; make more negative to move it further right
               -.5,   #shifts top left 'tExt' to the right; make more negative to move it further right
               1.5,   #shifts bottom right 'teXt' to the left; make more positive to move it further left
               1.5),  #shifts top right 'texT' to the left; make more positive to move it further left
  vjustvar = c(-1,    #shifts bottom left 'Text' upward; make more negative to move it further up
               2,     #shifts top left 'tExt' downward; make more positive to move it further down
               -1,    #shifts bottom right 'teXt' upward; make more negative to move it further up
               2)     #shifts top right 'texT' downward; make more positive to move it further down
)

df1 <- data.frame(x1 = sample(c(-5:5), size = 100, replace = TRUE), y1 = sample(c(-5:5), size = 100, replace = TRUE))

ggplot(df1, aes(x1, y1)) + geom_point() +
  xlim(-6, 6) + ylim(-6, 6) + 
  geom_text(data = annotations1, aes(x = xpos, y = ypos, hjust = hjustvar, vjust = vjustvar, label = annotateText))

text moved slightly away from corners

Adjusting the hjustvar and vjustvar values moves the text boxes more and more toward the interior, no matter the scale of your axes.

##Example 2
annotations2 <- data.frame(
  xpos = c(-Inf, -Inf, Inf, Inf), ypos =  c(-Inf, Inf, -Inf, Inf),
  annotateText = c("Text", "tExt", "teXt", "texT"),
  hjustvar = c(-2, -2, 3, 3),
  vjustvar = c(-4, 5, -4, 5))

df2 <- data.frame(x2 = rnorm(100), y2 = rnorm(100))

ggplot(df2, aes(x2, y2)) + geom_point() +
  geom_text(data = annotations2, aes(x = xpos, y = ypos, hjust = hjustvar, vjust = vjustvar, label = annotateText))

text moved further inward, axis limits not set

like image 6
E. Moore Avatar answered Nov 10 '22 14:11

E. Moore