In base R, I like to make plots with time on the x-axis where the labels are shown in between long tick marks. For example, there may be tick marks at June 1 and June 31, but the text "June" shows up in between, centered around June 15. In base R, I simply draw 2 axes, one with the ticks and one with the labels.
However, I haven't been able to figure out how to make this style of axis in ggplot2.
labels = c("","June","")
almost works but tick marks only accept one length so something like axis.ticks.length = unit(c(.25,0,.25),"cm")
doesn't work.I think something like this might be possible with the ggh4x
package but I haven't been able to figure it out. I will be happy for any solution compatible with ggplot2, regardless of which package.
My solution is to assign the major x-axis breaks to the 15th of each month and the minor axis breaks to the 1st of each month. Then, in the theme()
function, I remove the major axis breaks and place more visual emphasis on the "minor" breaks.
Here is some data.
library(tidyverse)
library(nycflights13)
flights.df <- nycflights13::flights |>
group_by(year, month, day) |>
summarise(flights = n(),
delayed = sum(dep_delay > 10, na.rm = T),
.groups = "drop") |>
mutate(pct_delayed = delayed/flights*100,
date = as.Date(paste(year, month, day, sep = "-")))
flights.df
# A tibble: 365 × 7
year month day flights delayed pct_delayed date
<int> <int> <int> <int> <int> <dbl> <date>
1 2013 1 1 842 195 23.2 2013-01-01
2 2013 1 2 943 276 29.3 2013-01-02
3 2013 1 3 914 234 25.6 2013-01-03
4 2013 1 4 915 218 23.8 2013-01-04
5 2013 1 5 720 129 17.9 2013-01-05
6 2013 1 6 832 178 21.4 2013-01-06
7 2013 1 7 933 149 16.0 2013-01-07
8 2013 1 8 899 116 12.9 2013-01-08
9 2013 1 9 902 102 11.3 2013-01-09
10 2013 1 10 932 106 11.4 2013-01-10
# ℹ 355 more rows
The basic plot looks like this, with the date labels placed at the beginning of each month.
ggplot(flights.df, aes(date, pct_delayed)) +
geom_point() +
scale_x_date(breaks = scales::date_breaks("1 month"),
labels = scales::label_date("%b"))
Here's the same graph, but with the major and minor x grid flipped. Notice the explicit addition of minor axis ticks. You can specify any custom handling of the axis ticks.
ggplot(flights.df, aes(date, pct_delayed)) +
geom_point() +
scale_x_date(breaks = flights.df$date[flights.df$day == "15"],
minor_breaks = flights.df$date[flights.df$day == "1"],
labels = scales::label_date("%b"),
guide = guide_axis(minor.ticks = TRUE)) +
theme(axis.ticks.x = element_blank(),
axis.minor.ticks.x.bottom = element_line())