ggarrange always covers bottom right x-axis with axis title - r

So I've been trying to stitch a set of four plots together and the bottom right x-axis always gets covered with axis title. Originally I thought it might have been because the bottom right plot had a slightly larger y-axis but it doesn't matter which graph I stick in the bottom right corner it always gets covered up....
Here is my code:
tiff('Predictors.tiff', units = "in", width = 12, height = 12, res = 1200)
ggarrange(PC5,PN5,HW5,CN5, ncol = 2, nrow = 2)
annotate_figure(figure,top = text_grob("Predictors of N Mineralization", size = 20),
left = text_grob("N mineralization after 6 months (mg/kg)", size = 20, rot = 90))
dev.off()
PC5,PN5 etc. are all names of plots

Related

How to reduce the vertical white space between plots using ggarrange in r

I had trouble trying to remove the vertical white space between each plot. I have several plots so I used ggarrange to combine them.
This is my code:
figure <- ggarrange(lima_exceso,loreto_exceso,amazonas_exceso,madre_exceso,
callao_exceso,apurimac_exceso,ancash_exceso,
sanmartin_exceso, ica_exceso,ayacucho_exceso,
arequipa_exceso, piura_exceso,junin_exceso,pasco_exceso,
cusco_exceso,lambayeque_exceso,huancavelica_exceso,
puno_exceso,tumbes_exceso,lalibertad_exceso,
tacna_exceso,huanuco_exceso,cajamarca_exceso,
labels = c(""),
ncol = 4, nrow = 6)
annotate_figure(figure,
top = text_grob("Exceso de fallecidos (media móvil-7d)",
color = "black", face = "bold", size = 12),
bottom = text_grob("Data source: \n Minsa ",
color = "black", hjust = 0, x = 0, face = "italic",
size = 8), fig.lab = "", fig.lab.face = "bold",
fig.lab.pos = "top.right" , fig.lab.size = 8)
ggsave(file="ex31.pdf" , height = 350, units = "mm" , width = 340)
This is the outcome:
As you can see there is a lot of vertical space between the graphics and that's why the title is too close from the plots. The margin of the pdf is tiny.
So I tried to narrow that space by setting margins for each plot (just for the first column), however, the outcome was not what I wanted.
I add this line code to the plots of the first column:
+theme(plot.margin = unit(c(-0.25,0.5,-0.25,0.5), "lines"))
This was the outcome:
As you can see I narrowed the vertical space but now the plots of the first column are taller than the others, and the title of the first plot (right corner) is too close from the ggarrange title. I want to reduce the space between the plots but I don't want to modify anything else.
Is there a way to reduce the vertical space of my plots using ggarrange?

Vertical x labels out of plot

I have a plot where I have introduced vertical x axis labels via las = 2. Those labels are category words. These words are too long, they protrude out of the picture. What can I do, so that they fit into the picture?
This is the code (the x axis labes are German words):
categories <-c("Traditionsbewusst / Heimatverbunden","Bekanntheit
","Jugendlich / Modern
","Professionell
","Sozial engagiert
","Aufstrebend / Motiviert
","Umwelt / Nachhaltigkeit
","Sympathisch
","Familienfreundlich
","Mitreißend
","Posetives Image
","Teamgeist
","Inovativ
")
Ergebnis<-c(2,1,2,2,2,2,2,2,2,2,3,2,2)
plot(Ergebnis,type = "b",main = "Profil Image",xlab = "",ylab = "Bewertung",axes =FALSE)
axis(1,at=1:13,labels = categories,las=2,cex.axis=0.8)
axis(2)
You can adjust the margins using par(mar(c(bottom, left, top, right))) where bottom, left, top, and right and the corresponding margin sizes in inches. In your case, running par(mar = c(15, 3, 3, 3)) before the plot() command seems to do the trick.

Rotating label using rot = on grid.arrange not working

I am trying to rotate one of the labels on my grid.arrange panel figure to look like the axis of all three plots, but this is not working using the methods I am finding online.
When I use a textGrob for control of the font size (which I need to be 24), using this code, I get this figure. I am inserting the rot= 90 argument but it isn't doing anything to the figure.
grid.arrange(d.a.plot1, d.b.plot1, d.c.plot1, ncol = 1, left = textGrob("Probability of remaining availabile", gp=gpar(fontsize=24, rot = 90)), bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))
When I use the standard grid.arrange code to add a rotated label using the code below, the position is fine, but then I can't adjust the font.
grid.arrange(d.a.plot1, d.b.plot1, d.c.plot1, ncol = 1, left = "Probability of remaining availabile", bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))
You just need to take rot = 90 out of gpar and pass it directly to textGrob:
# Simulate the plot grobs:
f <- function() cowplot::as_grob(~plot(rnorm(100), rnorm(100)))
grid.arrange(f(), f(), f(), ncol = 1,
left = textGrob("Probability of remaining availabile", rot = 90,
gp = gpar(fontsize=24)),
bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))

Left-aligning ggplot when saved while using a fixed aspect ratio

I'm building a custom ggplot theme to standardize the look & feel of graphs I produce. The goal is more complex than this minimal example, so I'm looking for a general solution. I have a few key goals:
I want all graphs to export at the same size (3000 pixels wide, 1500 pixels high).
I want to control the aspect ratio of the plot panel itself.
I want to use textGrobs to include figure numbers.
I want the image to be left-aligned
The challenge I'm facing is that when combining these two constraints, the image that gets saved centers the ggplot graph within the window, which makes sense as a default, but looks bad in this case.
I'm hoping there's a general solution to left-align the ggplot panel when I export. Ideally, this will also work similarly for faceted graphs.
It seems that something should be possible using one of or some combination of the gridExtra, gtable, cowplot, and egg packages, but after experimenting for a few hours I'm at a bit of a loss. Does anybody know how I can accomplish this? My code is included below.
This is the image that gets produced. As you can see, the caption is left-aligned at the bottom, but the ggplot itself is horizontally centered. I want the ggplot graph left-aligned as well.
Graph output: https://i.stack.imgur.com/5EM2c.png
library(ggplot2)
# Generate dummy data
x <- paste0("var", seq(1,10))
y <- LETTERS[1:10]
data <- expand.grid(X=x, Y=y)
data$Z <- runif(100, -2, 2)
# Generate heatmap with fixed aspect ratio
p1 <- ggplot(data, aes(X, Y, fill= Z)) +
geom_tile() +
labs(title = 'A Heatmap Graph') +
theme(aspect.ratio = 1)
# A text grob for the footer
figure_number_grob <- grid::textGrob('Figure 10',
x = 0.004,
hjust = 0,
gp = grid::gpar(fontsize = 10,
col = '#01A184'))
plot_grid <- ggpubr::ggarrange(p1,
figure_number_grob,
ncol = 1,
nrow = 2,
heights = c(1,
0.05))
# save it
png(filename = '~/test.png', width = 3000, height = 1500, res = 300, type = 'cairo')
print(plot_grid)
dev.off()
I was able to find a solution to this that works for my needs, though it does feel a bit hacky.
Here's the core idea:
Generate the plot without a fixed aspect ratio.
Split the legend from the plot as its own component
Use GridExtra's arrangeGrob to combine the plot, a spacer, the legend, and another spacer horizontally
Set the width of the plot to some fraction of npc (normal parent coordinates), in this case 0.5. This means that the plot will take up 50% of the horizontal space of the output file.
Note that this is not exactly the same as setting a fixed aspect ratio for the plot. If you know the size of the output file, it's close to the same thing, but the size of axis text & axis titles will affect the output aspect ratio for the panel itself, so while it gets you close, it's not ideal if you need a truly fixed aspect ratio
Set the width of the spacers to the remaining portion of the npc (in this case, 0.5 again), minus the width of the legend to horizontally center the legend in the remaining space.
Here's my code:
library(ggplot2)
# Generate dummy data
x <- paste0("var", seq(1,10))
y <- LETTERS[1:10]
data <- expand.grid(X=x, Y=y)
data$Z <- runif(100, -2, 2)
# Generate heatmap WITHOUT fixed aspect ratio. I address this below
p1 <- ggplot(data, aes(X, Y, fill= Z)) +
geom_tile() +
labs(title = 'A Heatmap Graph')
# Extract the legend from our plot
legend = gtable::gtable_filter(ggplotGrob(p1), "guide-box")
plot_output <- gridExtra::arrangeGrob(
p1 + theme(legend.position="none"), # Remove legend from base plot
grid::rectGrob(gp=grid::gpar(col=NA)), # Add a spacer
legend, # Add the legend back
grid::rectGrob(gp=grid::gpar(col=NA)), # Add a spacer
nrow=1, # Format plots in 1 row
widths=grid::unit.c(unit(0.5, "npc"), # Plot takes up half of width
(unit(0.5, "npc") - legend$width) * 0.5, # Spacer width
legend$width, # Legend width
(unit(0.5, "npc") - legend$width) * 0.5)) # Spacer width
# A text grob for the footer
figure_number_grob <- grid::textGrob('Figure 10',
x = 0.004,
hjust = 0,
gp = grid::gpar(fontsize = 10,
col = '#01A184'))
plot_grid <- ggpubr::ggarrange(plot_output,
figure_number_grob,
ncol = 1,
nrow = 2,
heights = c(1,
0.05))
# save it
png(filename = '~/test.png', width = 3000, height = 1500, res = 300, type = 'cairo')
print(plot_grid)
dev.off()
And here's the output image: https://i.stack.imgur.com/rgzFy.png

Add second barplot to existing one manually (using add=T)

Is there a way in base R to manually add a second barplot to an existing one. I know how to do it if the two series are from the same data object (using barplot( ... beside=T)) or I guess one could draw rectangles (rect(...)) which barplot wraps. If your data is from different objects how can you then do it with the barplot function ? How to control bar positions?
I tried this using the space parameter (obviously not working):
h1 <- c(10,5,1)
h2 <- c(8, 3, 1)
barplot(h1, width = 0.5, space = 2, col='red')
barplot(h2, width = 0.5, space = 2.5, col='blue', add=T)
It is impossible to get the bars besides each other as when using the beside=T argument.
Desired output is something along this:
barplot(matrix(c(h1, h2), nrow=2, byrow=T), beside=T, col=c('red', 'blue'))
UPDATE: how it works
In order for me to finally - I hope - understand the width and space arguments, we can plot an axis and play with the parameters for the blue data.
barplot(h1, width = 0.5, space = 2, col='red')
axis(1, seq(0, 10, 0.5)) #way out of the plot region
barplot(h2, width = 0.25, space = c(4,2,4), col='blue', add=T)
From this it seem as (correct me if I am wrong):
1. width is the width of each bar - recycled as necessary
2. space controls the space to the previous bar (to the left) or to 0 for the first bar, and is calculated as width*space for the current bar - recycled as necessary. So the first blue bar starts at (space to 0) 0.25*4 = 1 and its right side is at 1+0.25 = 1.25; the second bar starts at 1.25+0.25*2 = 1.75, and its right side is at 1.75+0.25 = 2. And so forth...
You can do this:
h1 <- c(10,5,1)
h2 <- c(8, 3, 1)
barplot(h1, width = 0.5, space = 2, col='red')
barplot(h2, width = 0.5, space = c(3,2,2), col='blue', add=T)
And this will be the output:

Resources