1

I would like plot a line below a ggplot2 graph with text above it, something like this:

enter image description here

where the starting and ending point of the gene on the x axis can be specified.

My attempt so far:

require(ggplot2)
require(grid)
require(gridExtra)
data = data.frame(y = -log10(runif(100)), x = 1:100)
p = ggplot(data=data, aes(x, y)) + geom_point()
p = p + theme(plot.margin=unit(c(1, 1, 5, 1), "lines"))
t1 = textGrob("Gene1")
p1 = p + annotation_custom(grob=t1, xmin=0, ymin=0, xmax = 3, ymax=-.1)
print(p1)

which gives:

enter image description here

If I try to move the text down by adjusting ymax, then it disappears.

4
  • do you need precise positioning relative to the x-axis (ie in units of the data scale)? Commented Nov 21, 2014 at 16:01
  • see also this related question Commented Nov 21, 2014 at 16:57
  • also possibly related Commented Nov 22, 2014 at 18:28
  • @baptiste Yes, precise positioning is needed. Commented Nov 23, 2014 at 19:08

2 Answers 2

3

In my answer, I have changed a couple things: 1 - I changed the name of your data to "df", as "data" can cause confusion between objects and arguments. 2 - I removed the extra panel space around the main data plot, so that the annotation wasn't so far away.

require(ggplot2)
require(grid)
require(gridExtra)

# make the data
df <- data.frame(y = -log10(runif(100)), x = 1:100)

p <- ggplot(data=df, aes(x, y)) + geom_point()

# remove this line of code:
# p <- p + theme(plot.margin=unit(c(1, 1, 5, 1), "lines"))

# set up the plot theme for the annotation
blank_axes_and_thin_margin <- theme(axis.text = element_text(color="white"),
                    axis.title = element_text(color="white"),
                    axis.ticks = element_blank(),
                    panel.grid = element_blank(),
                    panel.border = element_blank(),
                    plot.margin=unit(c(0, 2, 0,2),"mm"))

# define the position of the arrow (you would change this part)
arrow_start <- min(df$x)
arrow_end <- mean(c(min(df$x), max(df$x)))
arrow_height <- 1

# here's the rectangle with the arrow
t2 <- ggplot(df, aes(x,y))+
  theme_bw()+
  geom_rect(aes(xmin=min(x), xmax = max(x)),
                ymin=0, ymax=4,fill="gray50")+
  coord_cartesian(ylim=c(0,4))+
  annotate(geom="text", label="Gene1", 
           x=20, y=2, size=6, color="black")+
  geom_segment(x=arrow_start, xend=arrow_end,
               y=arrow_height, yend=arrow_height, 
               color="black", arrow=arrow(ends="both"))+
  blank_axes_and_thin_margin
t2

# arrange the graphic objects here
# I use arrangeGrob because it allows you to use ggsave(), unlike grid.arrange
plot_both <- arrangeGrob(p, t2, nrow=2, heights=unit(c(0.75,0.25), "null"))
plot_both

# ta-da !

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Cool! These arrows are a little over-sized, is there a way to change that? Thanks!
you probably want to try the ?arrow help file. It isn't very thorough, but it mentions the control variables that may help you.
3

you can turn clipping off,

g <- ggplotGrob(p1)
g$layout$clip[g$layout$name == "panel"] <- "off"
grid.newpage()
grid.draw(g)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.