Reducing legend size in ggplot beyond default size - r

My goal is to make several plots with ggplot and combine them into a single plot using grid.arrange in the gridExtra package.
I'm having an issue in that the legends in my ggplot (while appropriately sized for a single plot) are too large when I try to place the plots side by side with grid.arrange. The resulting combined plots reduce the x-axis but keep the legend original size. So the result is a very skinny plot, next to an needlessly large legend. So I'd like to reduce the size of the legend in each plot, enough so that I can place my plots side by side. Or possible shrink them enough to bring them inside the actual plot without being to overbearing.
V1<-rnorm(10)
V2<-rnorm(10)
V3<-rnorm(10)
DF<-data.frame(V1,V2,V3)
ggplot(DF,aes(x=V1,y=V2,size=V3))+
geom_point(fill='red',shape=21)+
theme_bw()+
scale_size(range=c(5,20))
This plot command produces a standard legend size to the right of the plot.
I've tried using different theme elements:
+theme(legend.key.size = unit(0.5, "cm")
or
+theme(legend.key.width=unit(0.3,"cm"),legend.key.height=unit(0.3,"cm"),legend.position = c(0.7, 0.8))
And while I can make the legend larger using these theme commands, I can't make the legend any smaller than the default legend. So is there any way to shrink the legend beyond the default size?
I can also change the default size of my pdf device to make it wider and accommodate the large legends , but I'd like to work with a standard pdf size for now.

The whole point of a legend is to map aesthetics on the plot (e.g., color, fill, shape, or size) to levels identified in the legend. The parameters legend.key.size, .width, and .height adjust the size of the box surrounding the legend element. With color, fill, and shape you can make the legend items as small as you like, but with size, the size of the element tells you which bubble(s) correspond to which legend item, so the legend items must have sizes that correspond to what is on the plot.
Here are three possibilities that might help you:
Option 1: Put the legend inside the plot.
ggplot(DF,aes(x=V1,y=V2,size=V3))+
geom_point(fill='red',shape=21)+
theme_bw()+
scale_size(range=c(5,20))+
theme(legend.justification=c(1,0), legend.position=c(1,0))
Option 2: Use facet_wrap(...) if you can. This way you only get one legend for the set of plots.
Option 3: Use color and size, and then hide the size legend altogether.
ggplot(DF,aes(x=V1,y=V2,size=V3, color=V3))+
geom_point(shape=19)+
theme_bw()+
scale_size(range=c(5,20), guide="none")+
scale_color_gradient(high="#ff0000", low="#ffffcc")

Related

ggplot with the same width and height as ggsave(width=x, height=y)

Within R-Studio, I am generating plots with ggplot, then I save them with ggsave() for further use (I know, not ideal, but non-optional right now).
My problem is that when I generate the plot before saving it, R shows it to me in a particular size. With ggsave, I set width and height, so the elements displayed shift etc. I only see this after saving the plot.
I want R to show it to me before. I thus assume that I need to set the size of the plot within ggplot() somewhere , not in ggsave().
How can I do this in the least complicated fashion?
library(ggplot2)
ggplot(mtcars, aes(mpg,disp)) + geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
ggsave("rocketScience.png", width=10, height=7, unit="cm")
You can use the set_panel_size() function from the egg package.
With this function you can fix the panel size of the plot. This can be very useful when creating multiple plots that should have the exact same plotting area but use varying axis labels or something similar that would usually slightly change the panel dimensions. Especially useful for presentations with seamless animations or publications. It also ensures the same dimensions in the preview and the saved plot.
p <- ggplot(mtcars, aes(mpg,disp)) +
geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
#to view the plot
gridExtra::grid.arrange(egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
#to save the plot
ggsave(filename = "myplot.pdf", plot = egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
Within ggsave you can still manipulate the size of the whole "page" saved, but this will only influence the amount of white space around the plot. The actual panel size will stay fixed.
The example plot from above with 5cm or 15cm as width:
I don't believe this is achievable via ggplot settings; you might get around it if using RMarkdown, as you can set with and height of an output of a markdown chunk via fig.width and fig.height params.

Can I place my ggplot2 legend right beside the horizontal axis label?

In order to save as much as white space as I can, I would like to place the legend entry at the same height as the horizontal axis label. Can this be done and if so, how?
Here's a plot illustrating what I am hoping to achieve, with current and hoped-for legend position illustrated using a (manually added) green box.
I currently place the legend using theme(legend.position=c(0.87,0.1)) (noting that the exact coordinates are not relevant). Ideally, this route would allow for values outside of the [0,1] domain but it appears not to allow for that.
theme(legend.position="bottom") places the legend well outside of the plotting area, thus taking up more white space than I am willing to spare.
You just might have to play around with negative values regarding the y-coordinates of your legend.position-vector.
Here's an example:
library(ggplot2)
ggplot(iris, aes(Sepal.Width, Sepal.Length, color=Species))+
geom_line()+
facet_wrap(~Species)+
theme(legend.position=c(0.87,-0.01))
Note the -0.01 value. Is this what you're looking for?

How to preserve plot sizes when stacking with common x-axes in ggarrange?

I am trying to stack plots with common x- and y-axes in ggplot. What I want to do is have only the bottom plot show the x-axis labels and titles. But I've never been able to figure out how to do this cleanly in ggplot2 without having the bottom plot be squished by carrying the virtue of the x-axis labels/title. There must be an easy way to do this- everyone wants to stack graphs, right?!
I'm currently trying with ggarrange. Example code below. Note that the bottom plot gets compressed vertically because it has the tick and axis labels. I could just have the top two have white font labels/title, but then there is an unseemly amount of margin space between the three if you use that hack.
I'm definitely open to packages other than gpubr, but I am hoping for something not too elaborate that I can use in subsequent situations, as I'm sure I'll encounter this again...
Help, please!! -Ryan
#
require(ggplot2); require(ggpubr)
X=data.frame(seq(as.Date("2001-01-01"),as.Date("2001-12-31"),by='days')); colnames(X)='date'
X$Y1=sample(80:100,size=nrow(X),replace=T)
X$Y2=sample(100:120,size=nrow(X),replace=T)
X$Y3=sample(50:70,size=nrow(X),replace=T)
plot.Y1= ggplot(X, aes(x=date,y=Y1))+
geom_line()+lims(y=c(50,150))+
theme(axis.title.x = element_blank(),axis.text.x=element_blank())
plot.Y2= ggplot(X, aes(x=date,y=Y2))+
geom_line()+lims(y=c(50,150))+
theme(axis.title.x = element_blank(),axis.text.x=element_blank())
plot.Y3= ggplot(X, aes(x=date,y=Y3))+
geom_line()+lims(y=c(50,150))
x11(10,8)
ggarrange(plot.Y1,plot.Y2,plot.Y3,nrow=3,ncol=1)
Bottom plot is squished!
try this,
egg::ggarrange(plot.Y1,plot.Y2,plot.Y3,ncol=1)

How to enlarge the size of facet in R

I'm working on the following dataset where each facet shows the bleaching for one kind of coral at one site across the time period. My problem is how to enlarge the size of each facet to see the trend more clearly, as in current facets, it is hard to see the trend because of the small change in bleaching....
here is my code,
cb1<-aggregate(cb$latitude, list(Site=cb$site), mean)
cb$site=factor(cb$site, levels=cb1$Site[order(cb1$x)])
ggplot(cb,aes(year,bleaching)) +
geom_point() +
facet_grid(site~kind) +
geom_smooth(method="lm",color="grey") +
coord_cartesian(ylim=c(0,1))
due to the current size of the grid of facets, some lines seem flat but actually they are not.
You cannot really increase the sizes of the facets unless you increases the size of the plot overall. One option would be to save a large version of the plot:
p<-ggplot(cb,aes(year,bleaching))+geom_point()+facet_grid(site~kind)+geom_smooth(method="lm",color="grey")+coord_cartesian(ylim=c(0,1))
ggsave("file_name.jpg", plot = p, width = 24, height = 24, units = "in")
If you have limited space (e.g. the plot has to go on an A4 sheet) then the facet_grid_paginate function from ggforce would be a good option. It allows you to split faceted plots over multiple pages. You can define the number of rows and columns per page. See this link.
Alternatively, if you want to show that the lines are not flat more clearly, you can try toying with a couple of the arguments to facet_grid. facet_grid allows you to set the scales to free, free_x or free_y. Setting free_y would mean that each facet has its own y-axis (not necessarily between 0 and one (assuming you also removed the ylim=c(0,1). This would, however, make the the facets more difficult to compare with each other.

geom_bar not showing every values

I want to draw a bar plot, with ggplot and geom_bar, but it seems that the behavior of geom_bar is not consistent. I don't understand why.
My data is a time series of precipitations:
library(ggplot2)
library(data.table)
library(lubridate)
set.seed(42)
dt1 <- data.table(dateHeure=seq(ymd_hms("2014-06-04 13:30:00"),
ymd_hms("2014-10-20 08:30:00"), by='1 hour'),
rain=sample(c(rep(5,15), rep(10,15), rep(20,10),
rep(30, 5), 40, rep(0, 3262))))
Then i plot it, and not all the data appears... Why is some data missing?
ggplot(data=dt1)+
geom_bar(aes(x=dateHeure, y=rain),
stat="identity",
fill="blue") # doesn't work!
But if i add the variable color in aes, then the plot is correct!
ggplot(data=dt1)+
geom_bar(aes(x=dateHeure, y=rain, color="rain"),
stat="identity",
width=0.2) # work properly
So someone know why geom_bar doesn't work properly without color? Because i can't rely on it if sometimes not all the data is correctly plotted...
thanks!
edit: to respond to #eipi10, i added the plots. The strange thing is that when i resize the plot window in the first case, the data which is plotted changes!
Based on the edit to your question, I think I know what's happening: In the first plot, you use fill="blue". But the bin widths are very small compared to the overall range of the x-axis. This results in very, very thin vertical bars--so thin that you can't see some of them on your screen, but they appear when you expand the physical width of the plot.
On the other hand, in your second plot you used colour="rain", which adds a border to each bar, making each bar thicker, so they are visible, even when the physical width of the plot is relatively small.
Try adding colour="blue"(or "red" or whatever) to your first plot and I think you'll see all the bars, even without resizing. On the other hand, try changing colour="rain" to fill="rain" on your second plot and see if that creates the "disappearing data" effect on your second plot.
UPDATE: In response to your comment, you can use the colour parameter and then set the line width to get exactly the bar thickness you want, so you don't really need fill. For example:
ggplot(data=dt1)+
geom_bar(aes(x=dateHeure, y=rain),
stat="identity",
colour="blue", lwd=0.5)
Just set lwd (line width) to a value that gives you the bar-width you want. And, of course, you can also change the colour as well.

Resources