how to make scale_y_reverse work with scale_y_time

Viewed 311

I'm plotting HH:MM:SS on the y-axis against YYYY:MM on the x-axis, but am having issues trying to use scale_y_reverse with scale_y_time together.

sample data below:

library(hms)
library(ggplot2)

df_stack <- data.frame(yr_mn = rep(c("2020-01", "2020-02", "2020-03", "2020-04"),2),
                   timept_type = c(rep("A",4),rep("B",4)),
                   timept = as_hms(c("08:00:00", "09:10:00", "11:05:30", "10:45:00", "09:30:10", "10:00:00", "11:25:00", "08:40:00")))


df_stack %>%
  ggplot(., aes(x=yr_mn, y=timept, color=timept, fill=timept)) +
  geom_point() +
  geom_line(aes(group=1))+
  facet_wrap(vars(timept_type), scales="free", ncol=2) +
  scale_y_time(limits = c(as.POSIXct(as_hms("07:00:00")), as.POSIXct(as_hms("11:30:00")))) +
  scale_y_reverse() # this cause the y-axis labels to no longer be in hh:mm:ss format

If I comment out the last line scale_y_reverse() then the graph looks fine, but if I include it, the scale_y_reverse seems to convert the HH:MM:SS into seconds. I have no idea if it's something I'm doing incorrectly or if there's a built-in method within scale_y_time to resolve this. Thanks!

3 Answers

You can omit the scale_y_time and supply functions to scale_y_reverse to generate the labels and the breaks.

df_stack %>%
  ggplot(aes(yr_mn, timept, color = timept, fill = timept)) +
  geom_point() +
  geom_line(aes(group = 1)) +
  facet_wrap(vars(timept_type), scales = "free", ncol = 2) +
  scale_y_reverse(labels = function(x) as_hms(x),
                  breaks = seq(as.numeric(as_hms("07:00:00")), 
                               as.numeric(as_hms("11:30:00")),
                               1800))

Result:

enter image description here

After digging into the code for scale_x_reverse() and scale_x_time(), I've made a simplified version for my data (where x is time, and y is value).

Add a - in front of the variable to be reversed in the aesthetic, and add a reverse label function to scale_x_time(labels = function(x) -x)

ggplot(df, aes(x = -clock, y = points)) +
    geom_point() +
    scale_x_time(labels = function(x) -x)
    xlab("Clock") + ylab("Points")

Scale_x_reverse_time

Reversing the limits may easier and less error-prone.

ggplot(df, aes(x = clock, y = points)) +
    geom_point() +
    scale_x_time(limits = c(12*60*60,0)) # in seconds 
    xlab("Clock") + ylab("Points")
Related