Reputation: 1692
I need to draw line segments across (and on) the x-axis boundary of a ggplot2
figure so that I can make axis breaks. This SO question is similar but does not have an answer for how to implement multiple axis breaks and the top answer is rather cumbersome.
Example Data
set.seed(321)
dat <- data.frame(matrix(ncol = 2, nrow = 18))
colnames(dat)[1:2] <- c("Month", "Value")
dat$Month <- rep(c(1,2,10,11,20,21),3)
dat$Value <- rnorm(18,20,2)
This is the basic figure, note the theme is theme_bw()
. I would like to keep this theme so that this figure resembles others. In the similar SO question, the top answer does not use theme_bw()
.
library(ggplot2)
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
scale_y_continuous(breaks = seq(15,24,1),
limits = c(15,24)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"))
This is as far as I got because I could not find a way to extend the geom_segment()
across the x-axis boundary.
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
geom_segment(aes(x = 2.45, xend = 2.45,
y = -Inf, yend = 15)) +
geom_segment(aes(x = 2.55, xend = 2.55,
y = -Inf, yend = 15)) +
geom_segment(aes(x = 4.45, xend = 4.45,
y = -Inf, yend = 15)) +
geom_segment(aes(x = 4.55, xend = 4.55,
y = -Inf, yend = 15)) +
scale_y_continuous(breaks = seq(15,24,1),
limits = c(15,24)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"))
The ideal figure would look like the figure below, which I created 'by-hand' in MS Word which I am trying to avoid.
It would be great if ggbreak
had a way to do this but it currently does not as far as I am aware.
Upvotes: 0
Views: 1428
Reputation: 23737
The answer in the linked thread is not cumbersome and it works really well for this problem.
library(ggh4x)
#> Loading required package: ggplot2
x_end <- c(2.45, 4.45)
x_start <- x_end + 0.1
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
theme_classic() +
guides(x = guide_axis_truncated(
trunc_lower = c(-Inf, x_start),
trunc_upper = c(x_end, Inf)
)) +
## add the segments simply with text annotation - as suggested by teunbrand in the comment in the linked thread
annotate("text", y = -Inf, x = c(x_end, x_start), label = "I") +
coord_cartesian(clip = "off")
Upvotes: 3
Reputation: 173793
You need to turn off the limits off your y scale. Use the ylim
argument in coord_cartesian
instead, and set clip = 'off'
.
To get the look you are going for, it's probably easiest to add the geom layers as an annotation
.
Note also that the annotations are drawn underneath the panel border, so you need to turn that off. In the example below I have drawn it back in using annotation_custom
so that the subsequent annotations are drawn over it.
library(ggplot2)
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
scale_y_continuous(breaks = seq(15,24,1)) +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"),
panel.border = element_blank()) +
coord_cartesian(clip = 'off', ylim = c(15, 24.5)) +
annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
annotate('rect', xmin = c(2.33, 4.33), xmax = c(2.67, 4.67),
ymin = 14, ymax = 16, fill = 'white') +
annotate('segment', x = c(2.33, 2.67, 4.33, 4.67),
xend = c(2.33, 2.67, 4.33, 4.67), y = 14.2, yend = 15)
Upvotes: 4