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.

qed
  • 22,298
  • 21
  • 125
  • 196

2 Answers2

3

you can turn clipping off,

g <- ggplotGrob(p1)
g$layout$clip[g$layout$name == "panel"] <- "off"
grid.newpage()
grid.draw(g)
baptiste
  • 75,767
  • 19
  • 198
  • 294
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

Matt74
  • 729
  • 4
  • 8
  • Cool! These arrows are a little over-sized, is there a way to change that? Thanks! – qed Nov 21 '14 at 23:09
  • 1
    you probably want to try the `?arrow` help file. It isn't very thorough, but it mentions the control variables that may help you. – Matt74 Nov 22 '14 at 23:08