Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set interval between breaks on time axis

First let's create some example data. The times are stored using lubridate's hm as this seems the most suitable.

library(tibble)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date

(
  data <- tibble(
    Time = hm('09:00', '10:30'),
    Value = 1
  )
)
#> # A tibble: 2 x 2
#>   Time         Value
#>   <S4: Period> <dbl>
#> 1 9H 0M 0S         1
#> 2 10H 30M 0S       1

Here's how I'd like the plot to look. For now I've specified the breaks manually at half-hour intervals.

library(ggplot2)
library(scales)

ggplot(data, aes(Time, Value)) +
  geom_point() +
  scale_x_time(breaks = hm('09:00', '09:30', '10:00', '10:30'))

I'd like to create these breaks automatically at half-hour intervals. Trying to use scales::date_breaks gives an error.

ggplot(data, aes(Time, Value)) +
  geom_point() +
  scale_x_time(breaks = date_breaks('30 mins'))
#> Error in UseMethod("fullseq"): no applicable method for 'fullseq' applied to an object of class "c('hms', 'difftime')"

Trying to create the breaks using seq also gives an error.

seq(hm('09:00'), hm('10:30'), hm('00:30'))
#> Note: method with signature 'Period#ANY' chosen for function '-',
#>  target signature 'Period#Period'.
#>  "ANY#Period" would also be valid
#> estimate only: convert to intervals for accuracy
#> Error in if (sum(values - trunc(values))) {: argument is not interpretable as logical
like image 285
Greg Avatar asked May 28 '18 14:05

Greg


Video Answer


2 Answers

The error message you got, dealing with a method applied to an object of class "c('hms', 'difftime')", should give you a clue that there's a class issue here. First thing to do is check the class of your times, and check the docs (?hm), both of which will show you that hm actually returns a period object, not a datetime.

library(tidyverse)
library(lubridate)

class(data$Time)
#> [1] "Period"
#> attr(,"package")
#> [1] "lubridate"

So you need to change Time into a Date or similar object. There are different ways to do this, but I just quickly pasted today's date and Time together, then converting to a datetime object. The date I used doesn't matter if you don't actually need a date; it's basically a dummy for creating the object you need.

You also want scale_x_datetime rather than scale_x_date. Without setting a date_labels argument, you would have labels like "2018-05-28 09:00:00", so you can format those as just times by giving a formatting string to date_labels.

data %>%
  mutate(time2 = paste(today(), Time) %>% as_datetime()) %>%
  ggplot(aes(time2, Value)) +
  geom_point() +
  scale_x_datetime(breaks = scales::date_breaks("30 mins"), date_labels = "%H:%M")

Created on 2018-05-28 by the reprex package (v0.2.0).

like image 147
camille Avatar answered Oct 17 '22 21:10

camille


Using new breaks_width() function from the package scales.

ggplot(data, aes(Time, Value)) +
  geom_point() +
  scale_x_time(breaks = scales::breaks_width("30 min"))
like image 4
malexan Avatar answered Oct 17 '22 21:10

malexan