Is there a way to remove the white space surrounding a ggplot2 plot when the shape has been changed using coord_fixed()? I would like the white space above and below to be cropped away so that only the plotting area and axis labels remain. I am rendering the plot output in an R markdown file without saving.
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + coord_fixed(ratio = 1)
The code below produces the following plot:
When you use:
ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
coord_fixed(ratio = 1) +
ggsave('plot.jpg', width = 6, height = 1.5, dpi = 300)
You get a plot with less white space:
Another option could be to use the png or jpeg device:
p <- ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
coord_fixed(ratio = 1)
jpeg('plot.jpg', width = 600, height = 150)
p
dev.off()
If you are looking for a solution which also works in R markdown (i.e. output as PDF/HTML), this solved it for me: first set the aspect ratio and then remove the additional margin on the top via the theme() settings.
library(ggplot2)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, shape = Species, color = Species)) +
geom_point(size = 5) +
coord_fixed(ratio = 1/2) +
theme(plot.margin=unit(c(-0.30,0,0,0), "null")) # remove margin around plot
See also this blog post for more details.
Session info:
MacOs 10.13.6, R 3.6.3, ggplot2_3.3.1
Related
I'm doing something like the following. I tend to use cowplot for saving images of ggplot-generated plots but non-cowplot solutions are also fine. The first plot produces three facets (and one empty space) in a 2x2 arrangement, the second produces 6 facets in a 3x2 arrangement. I set base_height and base_width assuming a size of 2 square for each plot. In the images generated from the code below, the individual plots (each facet) are not quite the same size, across the two images.
library(ggplot2)
library(cowplot)
ggplot(mtcars, aes(x=mpg, y=hp))+
geom_point()+
facet_wrap(~cyl,ncol=2) +
ggtitle("hp vs. mpg, by cyl") +
theme_cowplot(font_size=10)
save_plot("car1.png", last_plot(), base_height=4, base_width=4)
ggplot(mtcars, aes(x=mpg, y=hp))+
geom_point()+
ggtitle("hp vs. mpg, by carb") +
facet_wrap(~carb,ncol=3)+
theme_cowplot(font_size=10)
save_plot("car2.png", last_plot(), base_height=4, base_width=6)
I tried including the png files in the post but they each get scaled differently so it would be misleading.
I know I could generate each facet separately as its own plot and use plot_grid, and then base_height and base_width would set the size of each plot on its own, but is there any way to use facet_wrap or facet_grid and set the absolute size when saved of each facet?
Does cowplot::align_plots work for you?
library(ggplot2)
library(cowplot)
p1 <- ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point() +
facet_wrap(~cyl, ncol = 2) +
ggtitle("hp vs. mpg, by cyl") +
theme_cowplot(font_size = 10)
p2 <- ggplot(mtcars, aes(x = mpg, y = hp)) +
geom_point() +
ggtitle("hp vs. mpg, by carb") +
facet_wrap(~carb, ncol = 3) +
theme_cowplot(font_size = 10)
twoplots <- align_plots(p1, p2, align = "hv", axis = "tblr") #tblr' for aligning all margins
save_plot("car1.png", ggdraw(twoplots[[1]]))
save_plot("car2.png", ggdraw(twoplots[[2]]))
I am a newbie attempting to change the width of a ggplot, so that I am can arrange different plots(heatmap and dotplot) in the same figure. However, after hours of trying to reduce the width of the dotplot, I am about to give up.
Code for heatmap (maybe not relevant):
heatmap_GO_NES_1<-ggplot(data=long_frame_GO_NES_1) +
geom_tile(mapping = aes(
x = factor(timepoint,levels = c("6h","12h","24h")),
y =bio_process,fill = NES)) +
ylab(label="Biological process") +
theme(axis.title.x=element_blank()) +
scale_fill_gradient(low="red",high="green")+
facet_grid( group ~. , scales="free",space="free")+
theme(axis.text.x = element_text(angle = 90))+
theme(strip.text.y = element_text(size = 8))
heatmap_GO_NES_1
Code for dotplot:
dot_GO_NES_1<- ggplot(data=long_frame_GO_NES_2)+
geom_count(mapping=aes(x=timepoint, y =bio_process, size=setsize))+
theme(axis.title.x=element_blank(), axis.text.x=element_blank(),
axis.ticks.x=element_blank(),axis.title.y=element_blank(),
axis.text.y=element_blank(),axis.ticks.y=element_blank())
dot_GO_NES_1
Code for figure:
plot_grid(heatmap_GO_NES_1,dot_GO_NES_1)
Obviously, the dotplot is stealing all the figure space, so that my heatmap does not show up in the figure.
TL;DR - you need to use the rel_widths= argument of plot_grid(). Let me illustrate with an example using mtcars:
# Plots to display
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_point()
p2 <- ggplot(mtcars, aes(x='X', y=disp)) + geom_point(aes(size=cyl))
Here are the plots, where you see p2 is like your plot... should not be too wide or it looks ridiculous. This is the default behavior of plot_grid(), which makes both plots the same width/relative size:
plot_grid(p1,p2)
Adjust the relative width of the plots using rel_widths=:
plot_grid(p1,p2, rel_widths=c(1,0.3))
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.
I'm having issues with changing the size of the title, X-Y labels, X-Y axis text for my ggplot2. I'm using ggsave to save the plot as a jpg.
p <- ggplot()
p + theme(axis.title = element_text(size=30), axis.text.y = element_text(size=30),
axis.text.x = element_text(size=30))
but changing the sizes of these texts doesn't change anything on the plot. Would anyone know how to properly change the text sizes?
So I fixed the issue I was having so the changes I make to theme are not affecting the plot (I've tested with changing text color), however the size of the axis text still does not change.
p <- ggplot(d[d$user==i,], aes(x=date, y=url, group=user, label=user)) + geom_line() + geom_point() +
labs(list(title=i, x="Date and Time", y = "URL")) + # Plot labels
axis.POSIXct(1, at=seq(daterange[1], daterange[2], by="hour")) # Set x axis range to first and last date-time in data
p <- p + modifiedtheme
ggsave(plot = p, filename = "sample.jpg", height=2, width=6)
Here is a minimal, fully reproducible version of the problem (or lack of any problem, as comments have pointed out). Your own posted code appears to be correct, but maybe this example will help you solve whatever the real problem is:
library(ggplot2)
p1 = ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, colour=Species)) +
geom_point()
p2 = ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, colour=Species)) +
geom_point() +
theme(axis.title=element_text(size=30))
ggsave("figure1.jpg", plot=p1, height=3, width=4, units="in", dpi=150)
ggsave("figure2.jpg", plot=p2, height=3, width=4, units="in", dpi=150)
I'd like to add a footnote citation to my 3-panel facet grid plot produced in R. It's a footnote to credit the data source. I'd ideally like to have it below and external to all three axes---preferably in the lower left.
I'm using ggplot2 and also ggsave(). This means I can't use grid.text()-based solutions, because that only draws on the x11() window, and can't be added to the ggplot object.
Using instead png() ...code... dev.off() does not appear to be an option because I need ggsave's resizing parameters, and find this command produces better, clearer prints (that are also much faster, because I'm not printing to the screen).
Here's my basic code:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle)
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
I've tried:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle)
print(p1)
grid.text(unit(0.1,"npc"),0.025,label = "Data courtesy of Me")
grid.gedit("GRID.text", gp=gpar(fontsize=7))
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
This appropriately puts the footnote in the lower left corner on the x11() display, external to the plots, but unfortunately, since it isn't applied to the p1 object, it isn't saved by the ggsave command.
I've also tried:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle) +
annotate("text", label = "Footnote", x = 0, y = 10, size = 5, colour = "black") +
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
This successfully prints using ggsave, however it has the following problems:
It is repeated 3 times, in each of the 3 facets, rather than 1 time.
It is contained within the plots, rather than external to them.
Text is difficult to place---seems to be using plot units (my x-axis is date, so 0 puts it around 1970).
The text size doesn't seem to change despite my size parameter.
A couple of related links from when I explored this...
ggplot2 footnote
(doesn't work with ggsave)
How to label the barplot in ggplot with the labels in another test result?
(is inside the plot, not external/below plot)
Different font faces and sizes within label text entries in ggplot2
(doesn't work with ggsave)
problem saving pdf file in R with ggplot2
ggplot2 now has this ability natively with no need for additional packages. ... + labs(caption = "footnote", ...)
library(ggplot2)
ggplot(diamonds, aes(carat, price, color = clarity)) +
geom_point() +
labs(title = "Diamonds are forever...",
subtitle = "Carat weight by Price",
caption = "H. Wickham. ggplot2: Elegant Graphics for Data Analysis Springer-Verlag New York, 2009.")
library(gridExtra)
library(grid)
library(ggplot2)
g <- grid.arrange(qplot(1:10, 1:10, colour=1:10) + labs(caption="ggplot2 caption"),
bottom = textGrob("grid caption", x = 1,
hjust = 1, gp = gpar(fontface = 3L, fontsize = 9)))
ggsave("plot.pdf", g)
Edit: note that this solution is somewhat complementary to the recent caption argument added to ggplot2, since the textGrob can here be aligned with respect to the whole figure, not just the plot panel.
Adding to the answer of Brandon Bertelsen: if you want to have the caption in the left corner, add
theme(plot.caption = element_text(hjust = 0))