Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2: scale_*_time formats incorrectly

Goal

Use ggplot2::scale_*_time to format a time axis in a particular way (with the most recent version of ggplot2).

Minimal Reprex

# Example data
tib1 <- tibble::tibble(
    x = 1:10,
    y = lubridate::as.duration(seq(60, 600, length.out = 10))
)

Using ggplot2::scale_*_time with format = "%R" doesn't work - the axes are formatted using %H:%M:%S:

# This doesn't work
ggplot2::ggplot(tib1) +
    ggplot2::geom_point(ggplot2::aes(x,y)) +
    ggplot2::scale_y_time(labels = scales::date_format(format = "%R"))

However, I can add the time variable (y) to an arbitrary date, and then format the resultant datetime object:

# This works
tib2 <- tib1 %>%
    dplyr::mutate(z = lubridate::ymd_hms("2000-01-01 00:00:00") + y)

ggplot2::ggplot(tib2) +
    ggplot2::geom_point(ggplot2::aes(x,z)) +
    ggplot2::scale_y_datetime(labels = scales::date_format(format = "%R"))

Obviously, I'd prefer not to add an arbitrary date to my times to get the axis to format correctly (which I had to do until ggplot2::scale_*_time was introduced, but hope to avoid now).


1 Answers

Your durations get silently converted to an hms object, which are always displayed as hh:mm:ss (i.e. hms). scales::date_format uses format which doesn't do anything with hms objects, other than converting them to character vectors. Ideally, it would be easy to have a proper format.hms method that can control how much is shown, but as it stands hms:::format.hms doesn't actually take any format argument.

A solution is to simply delete the first three characters:

ggplot2::ggplot(tib1) +
  ggplot2::geom_point(ggplot2::aes(x,y)) +
  ggplot2::scale_y_time(labels = function(x) substring(x, 4))
like image 113
Axeman Avatar answered Jan 03 '26 15:01

Axeman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!