Arrange list of ggplot plots and adjust spacing/margin - r

I have a function that creates a list of ggplot plots. I'm currently using patchwork to arrange the plots together in a way that I can knit to Word, but I'm having a hard time with the way it looks when it renders. The output currently looks like this:
I'd like to make it so that it looks like this:
Currently, my code is the following:
patchwork_plots <- Reduce(`+`, plots)
patchwork_plots +
plot_layout(ncol=2)
I've tried a few different packages and different ways of adjusting, but nothing really seems to work. Any suggestions would be great.

A simple solution is to just change your aspect ratio and width= and height= of the plot. The graphics in your plots will not scale the same as the text in the plot, but will depend on the resolution and size/aspect ratio of your graphics device. Here is an example that shows 3 very different-looking plots that can result from adjusting the aspect ratio of your output.
library(ggplot2)
# intentionally crowded plot
gplot(mtcars, aes(mpg, disp)) + geom_point() +
facet_wrap(factor(cyl)~factor(carb), scales='free') +
labs(x='mpg is here and this is long', y='disp is here and this is long too!')
Width = 4, Height = 3
ggsave('plot4_3.png', width=4, height=3)
Width = 8, Height = 5
ggsave('plot8_5.png', width=8, height=5)
Width = 12, Height = 9
ggsave('plot12_9.png', width=12, height=9)

Related

Adjust bin width with geom_col()

I'm having a trouble with the binwidth of my col graphics.
I'm trying to show the highest/lowest suicide rate by country on the same page using shiny.
But, the country names are overlaping one another as you can see below:
How can i adjust this?
There are quite a few possibilities for resizing and adjusting things so that your long axis labels "fit" on a column plot (or any other ggplot for that matter). I'll go through some options here.
First of all... a sample dataset, since we did not get a suitable reprex from your question.
df <- data.frame(
x=c('Text1', 'Text2', 'Long Text Here', 'Really Really Long Text Label Here', 'Text5', 'Text6', 'Text7'),
y=c(sample(1:20, 7, replace=TRUE)))
df$x <- factor(df$x, levels=df$x) # making sure ggplot doesn't alphabetically sort!
library(ggplot2)
p <- ggplot(df, aes(x,y)) +
geom_col(aes(fill=x), show.legend = FALSE)
p
There's your overlapping labels. Now for some options:
Option #1: Resize the plot
One very simple method to "solving" the problem is to realize that R handles graphics... kind of funny. The look of a particular plot depends on the resolution and aspect ratio of the graphics device. Not only that, but text does not scale the same as the other plot elements. This means that you can fix the problem by forcing a different aspect ratio.
# this was used to create the above plot
ggsave('original.png', width=8, height=5)
# changing the aspect ratio produces the plot below on my graphics device
ggsave('resized.png', width=12, height=5)
Option #2: Change the Text Size
The other option is to make your text size for the axis labels smaller. The result is really similar to just resizing the plot.
p + theme(axis.text.x=element_text(size=6))
Option #3: Angle the Text
One really good option is to angle your text using the theme() element again. Note that when you do this you want to change the default alignment of your labels. Set hjust=1 so that the text is "right aligned". If you are setting your angle to 90°, you will also want to set your vjust=0.5 to make the text aligned with the tick mark vertically. Here I'll show you a 45° angled text option:
p + theme(axis.text.x=element_text(angle=45, hjust=1))
Option #4: Wrap Text Labels
One of my go-to favorite options here is to wrap the text label. There are a few ways to do this, but I prefer using wrap_format() from the scales package and a scale_* function. Note, the number given to wrap_format(X) indicates that wrapping should happen after X number of characters in the label.
library(scales)
p + scale_x_discrete(labels=wrap_format(22))
Option #5: Combine all Above
The best way to fix your problem is to use a combination of all techniques above to get the chart to look the way you believe looks most satisfying. This will depend on how many columns you have in your shiny plot and how you generate that plot (user input or always the same, etc). So it's up to you here.
p + scale_x_discrete(name=NULL, labels=wrap_format(22)) +
scale_y_continuous(expand=expansion(mult=c(0,0.15))) +
theme_classic() + #important to put this before overwriting individual theme elements!
theme(
axis.text.x=element_text(angle=40, hjust=1, size=15),
axis.text.y=element_text(size=15),
panel.grid.major.y=element_line(color='gray75', linetype=2))
You can flip your graph horizontally, it will be better for the readers. You can add this to your graph to flip it:
coord_flip()

Adjust plot axis labels to fit in .pdf

I'd like to save a histogram as .pdf but when I do it not all x-axis labels are visible. Is it there a way to automatically adjust the size of the plot so that all labels fit nicely and can be read? Thanks a lot in advance for your help!!
# Example data
dd <- iris
dd$Species <- as.character(dd$Species)
dd$Species[dd$Species=="setosa"] <- "setosa and more text that should also fit in the pdf"
dd$Species[dd$Species=="versicolor"] <- "versicolor and more text that should also fit in the pdf"
dd$Species[dd$Species=="virginica"] <- "virginica and more text that should also fit in the pdf"
dd$Species <- as.factor(dd$Species)
# Plotting & saving as .pdf
windows()
plot(dd$Species)
dev.copy(pdf, file="%/test.pdf") # % is the directory in my computer
dev.off()
If the problem is you need give more information on each label with more text, you can use next line
dd <- iris
dd$Species <- as.character(dd$Species)
dd$Species[dd$Species=="setosa"] <- "setosa is the name \n of iris-more text"
dd$Species[dd$Species=="versicolor"] <- "versicolor is the name \n of iris-more text "
dd$Species[dd$Species=="virginica"] <- "virginica is the name \n of iris-more text"
dd$Species <- as.factor(dd$Species)
plot(dd$Species)
When you print to pdf, what matters is the size of the pdf rather than the plot, for the labels to fit. In other words if you use
pdf("filename.pdf", width = W)
plot(dd$Species)
dev.off()
and the width parameter W is large enough, you should get a pdf in which the bars are wide enough so that all labels are visible.
This, however, may not be aesthetically pleasing, in which case you may want to try using ggplot2. This will enable you to play around with the labels more easily. For example, you can rotate all labels by an angle so that they all fit nicely
library(ggplot2)
ggplot(dd, aes(Species)) +
theme(axis.text.x = element_text(angle = 90)) +
geom_bar()
ggsave("filename.pdf")
You can also adjust the size of the font of the labels, or use a legend (which may be a neater way of listing all your labels in order, if there are too many - you can also colour each label differently if you use fill = Species in aes). You can find out how to set these parameters by typing ?theme, and ggplot2 also has excellent documentation with lots of examples at http://docs.ggplot2.org.

Change plot dimensions in ggplot2

I want to create a single pdf file and put several plots in it using package ggplot2. However I need to reduce the width of one specific plot, among all. Here is the code:
invisible(pdf("foo.pdf"))
foo <- data.frame(x=rnorm(100), y=rnorm(100), class=factor(sample(2,1000,T)))
ggplot(foo, aes(x=x,y=y))+geom_point() # first plot
# For next plot I want to reduce the width
ggplot(foo, aes(x=class,y=y)) + geom_boxplot()
invisible(dev.off())
How to do it?
You can print in a viewport smaller than the full page,
library(grid)
grid.rect(width=unit(0.8, "npc"), gp=gpar(lty=2))
print(qplot(1,1), vp=viewport(width=unit(0.8, "npc")))

Remove white space (i.e., margins) ggplot2 in R

I'm trying to plot a pie chart using GGPLOT2 in R. I want to do this in such a way as to omit the extra margin space.
What I'm doing is similar to what sharoz did in this post here except I want to include a legend.
Here is what I'm doing:
ggplot(DATA, aes(x=factor(0),fill=factor(LABELS),weight=VALUES)) +
geom_bar(width=1) +
coord_polar(theta='y') +
guides(fill=guide_legend(title='LEGEND'))
Assuming you are talking about the extra white space above and below the figure, the easiest solution is just to tweak the size of the graphics device. Here is aspect ratio is the key. If the aspect ratio of the graphics device matches that of the plot, you get rid of a lot of the whitespace.
What I use to save the plot is ggsave, in code:
ggplot(DATA, aes(x=factor(0),fill=factor(LABELS),weight=VALUES)) +
geom_bar(width=1) +
coord_polar(theta='y') +
guides(fill=guide_legend(title='LEGEND'))
ggsave("plot.png", width = 10, height = 5)
Just play around with width and height in ggsave until you are happy with the result.

automatically adjust R plot size in a PDF output

When using the pdf() function in R for saving a plot in an external file, we can specify width and/or height to adjust the size of the plot. However, there are situations when we obtain multiple plot (say using par(mfrow=c(2,4))). In this situation, it's kind of difficult to determine what is the best width and height for the PDF file in order to have all plots displayed properly. Is there a way to let R automatically "fit the plots" in the PDF file? I searched the arguments in pdf() and tried some, but the results are not satisfactory. Thank you very much!
How about something using ggplot?
require(ggplot2)
# Bogus data
x <- rnorm(10000)
y <- as.factor(round(rnorm(10000, mean=10, sd=2), 0))
df <- data.frame(vals=x, factors=y)
myplot <- ggplot(data=df, aes(x=vals)) +
geom_density() +
facet_wrap(~ factors)
ggsave(filename="~/foo.pdf", plot=myplot, width=8, height=10, units="in")
EDIT: Should you need to print over multiple pages, see this question.

Resources