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 !
