How to increase the space between facet boxes and plot edges? [duplicate] - r

This question already has answers here:
Distancing `facet_grid` strips from the faceted canvas?
(2 answers)
Closed 2 years ago.
I am using facet_grid to create a title in my plot that is surrounded by a black box with white background colour. I wonder how I could increase the space between this box with the title and the upper edge of my plot. Below I show a similar plot and I give a fake code to play with:
library(ggplot2)
library(cowplot)
library(ggpubr)
theme_set(theme_cowplot())
df1 <- data.frame(x = 1:12, y = (1:12)^2, grp=c('A', 'B', 'C'), depth=c("5m","5m","5m","5m"))
p1 <- ggplot(df1, aes(x, y, color=grp)) + geom_point() + facet_grid(.~depth) +
theme(strip.background = element_rect(colour = "black", fill = "white", size = 1.5, linetype = "solid"))
p1
Does anyone know how to do it? An alternative to increase space between the facet box and the upper edge of the plot could be also to do not use facet_grid. However, I couldn't find an alternative way to draw a title with a black box surrounding. If you have other way instead of using facet_grid is welcome.

Using #Dekike link:
ggplot(df1, aes(x, y, color=grp)) +
geom_point() +
facet_grid(.~depth) +
theme(strip.background.x = element_rect(colour = "black", fill = "white", size = 1.5, linetype = "solid"),
strip.placement = "outside",
strip.switch.pad.grid = unit(0.2, "in"))

Related

Adding visual embellishment in a custom ggplot theme

I'm currently prototyping custom ggplot themes for use within my organisation. Currently, the theme looks like this (using mtcars data):
I would like to add a solid-colored bar (in the org's primary color) underlining the chart title region to act as an easily scalable type of branding (rather than a jpeg logo which restricts the aspect ratio and size of the charts). I made a mockup of the effect I'm trying to achieve in paint:
I'm aware of annotate() but as far as I understand it that function only accepts arguments corresponding to x and y coordinates in the plotting area, so I don't know how to create an annotation that is bound to a point outside of the plotting area
I would use annotation_custom using a grid::linesGrob here. This allows you to place the line relative to the panel without having to use the plot limits, which can produce inconsistent results. It also allows the line to extend beyond the left and right limits of the plotting area.
Suppose your plot is created a bit like this:
library(ggplot2)
p <- ggplot(mpg, aes(displ, hwy, col = class)) +
geom_point() +
labs(title = "Test 1, theme 1", subtitle = "R default dataset",
caption = "Organization caption here",
y = "Fuel efficiency (mpg)",
x = "Engine displacement (litres)") +
scale_color_brewer(palette = "Set2", name = NULL) +
theme(panel.grid = element_line(color = "gray50"),
panel.border = element_rect(fill = NA),
legend.position = "top")
p
To add the line you can do:
p + coord_cartesian(clip = "off") +
annotation_custom(grid::linesGrob(
x = unit(c(-1, 2), "npc"), y = unit(c(1.2, 1.2), "npc"),
gp = grid::gpar(col = "orange2", lwd = 5)))
It is a bit hard without reproducible example, but you can use annotate with "segment" and define the x-values with Inf and the y-values with max(y) + some value depending on your theme layout like this:
library(ggplot2)
library(dplyr)
mtcars %>%
ggplot(aes(x = mpg, y = wt)) +
geom_point() +
annotate("segment", x = -Inf, xend = Inf, y = max(mtcars$wt) + 0.5, yend = max(mtcars$wt) + 0.5, colour = "orange", size = 2) +
coord_cartesian(clip = "off", ylim = c(min(mtcars$wt), max(mtcars$wt))) +
theme(plot.margin = unit(c(3,3,1,1), "lines"))
Created on 2022-07-27 by the reprex package (v2.0.1)

How to add a legend after arrange several plots using `ggarrange` from the ggpubr package?

I have got to create this arrange of different plots using ggarrange:
arrange <- ggarrange(P1,P2,P3,P4,P5, ncol=3,nrow = 2,common.legend = F, align = c("hv"))
arrange
I would like to add a common legend, so I did this:
arrange <- ggarrange(P1,P2,P3,P4,P5, ncol=3,nrow = 2,common.legend = T, align = c("hv"),legend="top")
arrange
However, I would like the legend was in the right lower part of the graph, in the "blank" space.
Do you know how could I do this?
Maybe it exist simpler and easier solution but just a quick way around is to create an empty plot with only the legend to be display and use to fill the last emplacement in ggarrange.
Here using iris dataset, you can first generate the five plot by specifying legend.position = "none" in theme to remove the legend:
library(ggplot2)
p2 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species))+
geom_point()+
theme(legend.position = "none")
Then, you draw an empty plot with only the legend to be display in the middle of the plot area. You can increase the size of all elements of the ggplot in order to make it visible on the final figure panel:
p3 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species))+
geom_point()+
lims(x = c(0,0), y = c(0,0))+
theme_void()+
theme(legend.position = c(0.5,0.5),
legend.key.size = unit(1, "cm"),
legend.text = element_text(size = 12),
legend.title = element_text(size = 15, face = "bold"))+
guides(colour = guide_legend(override.aes = list(size=8)))
Now, you can use ggarrange and specify p3 to be your last plot:
library(ggpubr)
ggarrange(p2,p2,p2,p2,p2, p3)
Does it answer your question ?

changing axis size in ggplot

I'm working on a plot where I would like to change the axis thickness to match the boarder of the facet labels. Somehow axis.line = element_line(color="black", size=0.5) doesn't work - any ideas why?
This is my code...
ggplot(datgg_final, aes(y = total_GLS, x = timing)) +
geom_boxplot(aes(fill = genotype)) +
facet_grid(col=vars(genotype)) +
theme(legend.position = "none") +
scale_fill_manual(values=c("#0496FF", "#53A548")) +
ggtitle("Effect of Timing") +
xlab("Days since Defence Induction") +
ylab("Total Glucosinolates (µmol g^-1 DW)") +
theme(strip.background = element_rect(color = "black", fill ="white", size=0.5, linetype="solid"),
axis.line = element_line(color="black", size=0.5))
... and the plot:
enter image description here
Even in most basic plots I cannot change any axis settings (except the linetype), this code just shows the normal boxplot, no red axes, no change in line size:
ggplot(datgg_final, aes(y=total_GLS, x=timing)) +
geom_boxplot() +
theme(axis.line=element_line(size=0.5, color="red"))
Fortunately, this seems to be a simple clipping issue. Unfortunately, this can't be adressed with the normal ggplot interface (as far as I know), but you could mess around in the gtable to produce the plot you want.
Consider the following plot:
library(ggplot2)
library(grid)
g <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
geom_point() +
facet_grid(~ Species) +
theme(strip.background.x = element_rect(colour = "black", fill = "white",
size = 0.5, linetype = "solid"),
axis.line = element_line(colour = "black", size = 0.5))
g
You can see that the apparent linewidths of the facet strips and the axes are unequal. We can turn of the clipping by messing around in the gtable:
# Convert plot to gtable
gt <- ggplotGrob(g)
# Find the strips
is_strip <- grep("strip", gt$layout$name)
# Turn off clipping at highest level
gt$layout$clip[is_strip] <- "off"
# Turn off clipping at the strip level
gt$grobs[is_strip] <- lapply(gt$grobs[is_strip], function(strip) {
strip$layout$clip <- "off"
strip
})
# Plot
grid.newpage(); grid.draw(gt)
Now the apparent linewidths are the intended linewidths, but it took quite some extra steps to get there. If somebody has a more elegant solution, be welcome to post an alternative.

Draw border around certain rows using cowplot and ggplot2

I want to somehow indicate that certain rows in a multipanel figure should be compared together. For example, I want to make this plot:
Look like this plot (with boxes around panels made with PowerPoint):
Here's the code I made to use the first plot. I used ggplot and cowplot:
require(cowplot)
theme_set(theme_cowplot(font_size=12)) # reduce default font size
plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot.mpg2 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot_grid(plot.mpg, plot.diamonds,plot.mpg2, plot.diamonds2, nrow=2,labels = c('A', 'B','C','D'))
Is there a change I can make to this code to get the borders that I want? Or maybe can I even make the panels A and B have a slightly different color than the background for panels C and D? That might be even better.
Since the result of plot_grid() is a ggplot object, one way to do this is to use nested plot grids: one plot_grid() for each row, with the appropriate border added via theme().
plot_grid(
# row 1
plot_grid(plot.mpg, plot.diamonds, nrow = 1, labels = c('A', 'B')) +
theme(plot.background = element_rect(color = "black")),
# row 2
plot_grid(plot.mpg2, plot.diamonds2, nrow = 1, labels = c('C', 'D')) +
theme(plot.background = element_rect(color = "black")),
nrow = 2)

Placing ggplot2 shape annotations into titles

I am trying to insert a shape (and fill color) into a title/subtitle, but cannot find the syntax to do so:
library(tidyverse)
D <-diamonds %>% filter(color=="D") %>%sample_frac(0.1)
G <-diamonds %>% filter(color=="G") %>% sample_frac(0.1)
ggplot(D, aes(x=carat, y=price))+
geom_jitter(data=G)+geom_point(shape=6)+
geom_jitter(data=D)+geom_point(shape=22, fill='red')+
labs(title, "This is a title",
subtitle=
"D diamonds (insert shape 22 fill red) and G diamonds (shape 6 color black)",
caption = "what I want is to insert the shape and fill color into the (sub)title")
Suggestions? Annotate seem designed to work only in the plot-space.
A possible work-around from working with images is to use a legend to get the look you want. This involves first making a legend. I used the color aesthetic to make the legend, one for each points layer. The strings I give in aes will be the label legends.
I modify the legend via scale_color_manual. This involves getting the labels in the right order and setting the colors. In addition I use guide_legend options to move the labels to the left of the key boxes (they default to the right) and get the right shapes and fills for the points.
Then, in theme, the legend can be moved to the top left, the key boxes can be filled with white instead of grey and reduced in size, and the space around the legend can be reduced.
This all looks like:
ggplot(D, aes(x = carat, y = price))+
geom_jitter(data = G) +
geom_point(data = G, aes(color = "and G diamonds"), shape = 6) +
geom_jitter() +
geom_point(aes(color = "D diamonds"), shape = 22, fill='red') +
labs(title = "This is a title") +
scale_color_manual(name = NULL, values = c("black", "black"),
limits = c("D diamonds", "and G diamonds"),
guide = guide_legend(label.position = "left",
override.aes = list(shape = c(22, 6),
fill = c("red", "black")) ) ) +
theme(legend.direction = "horizontal",
legend.position = "top",
legend.justification = "left",
legend.key = element_rect(fill = "white"),
legend.key.size = unit(.5, "mm"),
legend.margin = margin(b = 0, 0, 0, 0) )
Starting in the current development version of ggplot2, ggplot2_2.1.0.9001, there is a legend.box.spacing option in theme to reduce the space between the plot and the legend. I thought legend.box.spacing = unit(2, "mm") looked pretty good.

Resources