How to make a chain of ggplots and draw arrows between them? - r

For a project I need to draw some plots and put arrows between them as and indication of a sequence. I was wondering if I could do that with ggplot. Is it possible to draw a clean, big arrow with ggplot2 and add it two the final multiplot?
As an example I use this code to draw a plot:
library(ggplot2)
ggplot(diamonds, aes(clarity, fill=cut)) + geom_bar()
For the project I need to draw three plots like that. The result should be something like this:
Does anyone have a solution? Many thanks in advance!

Here's one approach:
library(ggplot2)
library(gridExtra)
library(grid)
library(png)
download.file("https://www.wpclipart.com/signs_symbol/arrows/arrow_comic/Arrow_comic_right_gray.png",
tf <- tempfile(fileext = ".png"),
mode="wb")
arrow <- rasterGrob(readPNG(tf))
p <- ggplot(diamonds, aes(clarity, fill=cut)) +
geom_bar()
grid.arrange(p + guides(fill = "none"),
arrow,
p + guides(fill = "none"),
arrow,
p,
ncol=5, widths=c(2/10, 1.75/10, 2/10, 1.75/10, 2.5/10))

Related

ggsave() options for grid arrangements in ggplot

ggsave() doesn't seem to work with the grid package (see below). How do I save this combination of plot p1 and plot p2. The following code only save the last plot p2 that ggplot() sees.
library(tidyverse)
p1 <- ggplot(mpg, aes(fl)) + geom_bar()
p2 <- ggplot(mpg, aes(cty, hwy)) + geom_col()
grid.newpage()
grid.draw(rbind(ggplotGrob(p1), ggplotGrob(p2), size = "last"))
ggsave("mpg.png")
Consider using gridExtra. As explained in this vignette, gridExtra, building off of gtable (a higher-level layout scheme), provides more facility in arranging multiple grobs on a page, while grid package provides low-level functions to create graphical objects (grobs).
library(ggplot2)
library(gridExtra)
p1 <- ggplot(mpg, aes(fl)) + geom_bar()
p2 <- ggplot(mpg, aes(cty, hwy)) + geom_col()
p <- grid.arrange(p1, p2)
ggsave(plot=p, filename="myPlot.png")
I think you can do something like this.
#plotFile
g1=file.path(HomeDir,plotFile)
f1=grid.arrange(p1,p2, ncol=2, top=textGrob("Multiple Plots", gp=gpar(fontsize=12, font = 2))) #arranges plots within grid
g <- arrangeGrob(f1) #generates g
#save
ggsave(g1, g,width = 29.7, height = 21, units = 'cm') #saves g
You have to assign the new combination first then use ggsave() to print it.
# here I name it to_print
to_print <- rbind(ggplotGrob(p1), ggplotGrob(p2), size = "last")
ggsave(filename = "mpg.png", plot = to_print)
hope this helps!

plot(p) and plot(ggplot_gtable(ggplot_build(p))) don't seem to give same output when plot background is transparent

I have the following R ggplot code:
require(ggplot2)
require(ggthemes)
df <- data.frame(x=1:10, y=5*(1:10))
p <- ggplot(df, aes(x,y)) +
geom_point() +
theme_few() +
theme(plot.background = element_rect(fill='transparent', colour=NA), legend.position='top')
pdf('test.pdf', width=5, height=2)
plot(p)
plot(ggplot_gtable(ggplot_build(p)))
But I do get two different figures:
I like the first figure (i.e without the background grid outside panel area). However, I also need to use ggplot_build() for some other processing. Could you please help?
You could copy what ggplot2::print.ggplot does more directly. This seems to work.
pdf('test.pdf', width=5, height=2)
plot(p)
grid::grid.newpage()
grid::grid.draw(ggplot_gtable(ggplot_build(p)))
dev.off()

ggolot horizontal gaps contour

I've been trying to plot contour plots using ggplot2 and csv file. I can't figure out why there are horizontal gaps showing up across the image.
Here is the code:
library(ggplot2)
plot2 <- ggplot(data=thirtyfour,aes( x = X.m., y = Z.m., z = t_ca.2))
plot2
plot2 + geom_tile(aes(fill = t_ca.2) )+
scale_fill_continuous(limits=c(0,0.0219),
breaks=seq(0,0.0219, by=0.01),
low="blue",
high="yellow")
In the geom_tile aesthetic try adjusting the height parameter.
+geom_tile(aes(fill=t_ca.2, height=1)) +...
Otherwise, please provide reproducible example code.

show ggplot2 title without reserving space for it

I am trying to set titles to some ggplot2 charts, while leaving some without titles. Unfortunately, when title is set, the y axis and the plot shrink (see the plot on the right). I need to plot the title without changing the Y axis size, so that titled charts are on the same scale with the others (as in the middle plot).
grid.arrange(
(ggplot(mtcars, aes(mpg, hp)) + geom_point()),
(ggplot(mtcars, aes(mpg, hp)) + geom_point() +
geom_text(aes(22.5, 340, label="fake title", vjust = 1, hjust = .5, show_guide = FALSE))),
(ggplot(mtcars, aes(mpg, hp)) + geom_point() +
labs(title="real title")),
ncol=3)
I cannot use fake empty-string titles on the other plots, because I am short on space.
I could use the geom_text() method, if anyone can tell me how to make it look less garbled.
So, how do I removing any reserved space for the title above the plot, while still showing the plot title on and at the top of the plot area? The latter is done with theme(plot.title = element_text(vjust=-1)).)
Edit
Thanks to #baptiste for pointing out a more concise way to accomplish this. Given p1, p2, and p3 from below:
pl = lapply(list(p1,p2,p3), ggplotGrob)
grid.newpage()
grid.draw(do.call(cbind, c(pl, size="first")))
Original answer
You can build the ggplot grobs and standardize the heights parameter across plots:
p1 <- ggplot(mtcars, aes(mpg, hp)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, hp)) + geom_point() + labs(title="real title")
p3 <- ggplot(mtcars, aes(mpg, hp)) + geom_point() +
geom_text(aes(22.5, 340, label="fake title", vjust = 1, hjust = .5, show_guide = FALSE))
p1 <- ggplot_gtable(ggplot_build(p1))
p2 <- ggplot_gtable(ggplot_build(p2))
p3 <- ggplot_gtable(ggplot_build(p3))
p2$heights <- p1$heights
p3$heights <- p1$heights
grid.arrange(p1, p2, p3, ncol=3)
You can then use the title's vjust setting to move it off of the plot or further onto the plot, if you want:
p2 <- ggplot(mtcars, aes(mpg, hp)) + geom_point() +
labs(title="real title") +
theme(plot.title=element_text(vjust=-.3))
You should use annotate for this. If you use geom_text, it will print as many labels as there are rows in your data, hence the poor-looking overplotted label in your question. A painful work-around is to create a 1-row data frame to use as the data for the geom_text layer. However, annotate is intended for this sort of thing so you don't need a work-around. Something like:
annotate(geom = "text", x = 22.5, y = 340, label="fake title")
is good practice. Annotate is also useful for adding single horizontal or vertical lines to a plot, or to highlight a region by drawing a rectangle around it.

Rug plot does not work when specifying alpha colors?

This works:
plot(1:10, col=rgb(0,0,0,1))
rug(1:10, col=rgb(0,0,0,1))
And this does not work (no rugs are additionally plotted):
plot(1:10, col=rgb(0,0,0,0.9))
rug(1:10, col=rgb(0,0,0,0.9))
Why? And how can I fix this?
The reason why I need this is because I would like to add alpha colors so that overlapping "rugs" are darker. Without beeing able to specify alpha colors, I am only able to plot this:
plot(rep(1:10,100), rep(1:10,100), col=rgb(0,0,0,1))
rug(jitter(rep(1:10,100)), col=rgb(0,0,0,1))
# This is quite easy to do with ggplot2
# data
df = data.frame(x = rep(1:10,100), y = rep(1:10,100))
# code
library(ggplot2)
ggplot(df, aes(x=x, y=y)) +
geom_point() +
geom_rug(sides="b", position="jitter", alpha=0.2, colour="blue") +
scale_x_continuous(breaks=seq(0,10,by=2)) +
scale_y_continuous(breaks=seq(0,10,by=2))

Resources