Fast Tidy Tools for Date and Date-Time Manipulation.
timeplyr
Fast Tidy Tools for Date and Datetime Manipulation
This package provides a set of functions to make working with date and datetime data much easier!
While most time-based packages are designed to work with clean and pre-aggregate data, timeplyr contains a set of tidy tools to complete, expand and summarise both raw and aggregate date/datetime data.
Significant efforts have been made to ensure that grouped calculations are fast and efficient thanks to the excellent functionality within the collapse package.
Installation
You can install and load timeplyr
using the below code.
# CRAN version
install.packages("timeplyr")
# Development version
remotes::install_github("NicChr/timeplyr")
library(timeplyr)
Basic examples
Convert ts
, mts
, xts
, zoo
and timeSeries
objects using ts_as_tibble
library(tidyverse)
#> ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
#> ✔ dplyr 1.1.4 ✔ readr 2.1.5
#> ✔ forcats 1.0.0 ✔ stringr 1.5.1
#> ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
#> ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
#> ✔ purrr 1.0.2
#> ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::desc() masks timeplyr::desc()
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag() masks stats::lag()
#> ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
eu_stock <- EuStockMarkets %>%
ts_as_tibble()
eu_stock
#> # A tibble: 7,440 × 3
#> group time value
#> <chr> <dbl> <dbl>
#> 1 DAX 1991. 1629.
#> 2 DAX 1992. 1614.
#> 3 DAX 1992. 1607.
#> 4 DAX 1992. 1621.
#> 5 DAX 1992. 1618.
#> 6 DAX 1992. 1611.
#> 7 DAX 1992. 1631.
#> 8 DAX 1992. 1640.
#> 9 DAX 1992. 1635.
#> 10 DAX 1992. 1646.
#> # ℹ 7,430 more rows
Easily plot time series using time_ggplot
eu_stock %>%
time_ggplot(time, value, group)
For the next examples we use flights departing from New York City in 2013.
library(nycflights13)
library(lubridate)
flights <- flights %>%
mutate(date = as_date(time_hour))
time_by
Group your time variable by any time unit
flights_monthly <- flights %>%
select(date, arr_delay) %>%
time_by(date, "month")
flights_monthly
#> # A tibble: 336,776 x 3
#> # Time: time_intv_month [12]
#> # By: month
#> # Span: 2013-01-01 - 2013-12-31
#> date arr_delay time_intv_month
#> <date> <dbl> <tm_intv>
#> 1 2013-01-01 11 [2013-01-01, 2013-02-01)
#> 2 2013-01-01 20 [2013-01-01, 2013-02-01)
#> 3 2013-01-01 33 [2013-01-01, 2013-02-01)
#> 4 2013-01-01 -18 [2013-01-01, 2013-02-01)
#> 5 2013-01-01 -25 [2013-01-01, 2013-02-01)
#> 6 2013-01-01 12 [2013-01-01, 2013-02-01)
#> 7 2013-01-01 19 [2013-01-01, 2013-02-01)
#> 8 2013-01-01 -14 [2013-01-01, 2013-02-01)
#> 9 2013-01-01 -8 [2013-01-01, 2013-02-01)
#> 10 2013-01-01 8 [2013-01-01, 2013-02-01)
#> # ℹ 336,766 more rows
We can then use this to create a monthly summary of the number of flights and average arrival delay
flights_monthly %>%
summarise(n = n(),
mean_arr_delay = mean(arr_delay, na.rm = TRUE))
#> # A tibble: 12 × 3
#> time_intv_month n mean_arr_delay
#> <tm_intv> <int> <dbl>
#> 1 [2013-01-01, 2013-02-01) 27004 6.13
#> 2 [2013-02-01, 2013-03-01) 24951 5.61
#> 3 [2013-03-01, 2013-04-01) 28834 5.81
#> 4 [2013-04-01, 2013-05-01) 28330 11.2
#> 5 [2013-05-01, 2013-06-01) 28796 3.52
#> 6 [2013-06-01, 2013-07-01) 28243 16.5
#> 7 [2013-07-01, 2013-08-01) 29425 16.7
#> 8 [2013-08-01, 2013-09-01) 29327 6.04
#> 9 [2013-09-01, 2013-10-01) 27574 -4.02
#> 10 [2013-10-01, 2013-11-01) 28889 -0.167
#> 11 [2013-11-01, 2013-12-01) 27268 0.461
#> 12 [2013-12-01, 2014-01-01) 28135 14.9
If the time unit is left unspecified, the time
functions try to find the highest time unit possible.
flights %>%
time_by(time_hour)
#> # A tibble: 336,776 x 21
#> # Time: time_intv_hour [6,936]
#> # By: hour
#> # Span: 2013-01-01 05:00:00 - 2013-12-31 23:00:00
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> 7 2013 1 1 555 600 -5 913 854
#> 8 2013 1 1 557 600 -3 709 723
#> 9 2013 1 1 557 600 -3 838 846
#> 10 2013 1 1 558 600 -2 753 745
#> # ℹ 336,766 more rows
#> # ℹ 13 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
#> # tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
#> # hour <dbl>, minute <dbl>, time_hour <dttm>, date <date>,
#> # time_intv_hour <tm_intv>
time_complete()
Complete missing gaps in time
flights %>%
count(time_hour) %>%
time_complete(time_hour)
#> Assuming a time granularity of 1 hour(s)
#> # A tibble: 8,755 × 2
#> time_hour n
#> <dttm> <int>
#> 1 2013-01-01 05:00:00 6
#> 2 2013-01-01 06:00:00 52
#> 3 2013-01-01 07:00:00 49
#> 4 2013-01-01 08:00:00 58
#> 5 2013-01-01 09:00:00 56
#> 6 2013-01-01 10:00:00 39
#> 7 2013-01-01 11:00:00 37
#> 8 2013-01-01 12:00:00 56
#> 9 2013-01-01 13:00:00 54
#> 10 2013-01-01 14:00:00 48
#> # ℹ 8,745 more rows
We can also make use of timeplyr time intervals
quarters <- time_aggregate(flights$date, time_by = "quarter", as_interval = TRUE)
interval_count(quarters)
#> # A tibble: 4 × 2
#> interval n
#> <tm_intv> <int>
#> 1 [2013-01-01, 2013-04-01) 80789
#> 2 [2013-04-01, 2013-07-01) 85369
#> 3 [2013-07-01, 2013-10-01) 86326
#> 4 [2013-10-01, 2014-01-01) 84292
# Or simply
flights %>%
time_by(date, time_by = "quarter", as_interval = TRUE) %>%
count()
#> # A tibble: 4 x 2
#> # Time: time_intv_3_months [4]
#> # By: 3 months
#> # Span: 2013-01-01 - 2013-12-31
#> time_intv_3_months n
#> <tm_intv> <int>
#> 1 [2013-01-01, 2013-04-01) 80789
#> 2 [2013-04-01, 2013-07-01) 85369
#> 3 [2013-07-01, 2013-10-01) 86326
#> 4 [2013-10-01, 2014-01-01) 84292
Ensure full weeks by setting from to the start of the week
start <- dmy("17-Jan-2013")
flights %>%
time_by(date, "week",
from = floor_date(start, unit = "week")) %>%
count()
#> # A tibble: 52 x 2
#> # Time: time_intv_week [52]
#> # By: week
#> # Span: 2013-01-13 - 2013-12-31
#> time_intv_week n
#> <tm_intv> <int>
#> 1 [2013-01-13, 2013-01-20) 6076
#> 2 [2013-01-20, 2013-01-27) 6012
#> 3 [2013-01-27, 2013-02-03) 6072
#> 4 [2013-02-03, 2013-02-10) 6089
#> 5 [2013-02-10, 2013-02-17) 6217
#> 6 [2013-02-17, 2013-02-24) 6349
#> 7 [2013-02-24, 2013-03-03) 6411
#> 8 [2013-03-03, 2013-03-10) 6551
#> 9 [2013-03-10, 2013-03-17) 6556
#> 10 [2013-03-17, 2013-03-24) 6549
#> # ℹ 42 more rows
Check for missing gaps in time
missing_dates(flights$date) # No missing dates
#> Date of length 0
time_num_gaps(flights$time_hour, time_by = "hours") # Missing hours
#> [1] 1819
To check for regularity use time_is_regular
hours <- sort(flights$time_hour)
time_is_regular(hours, time_by = "hours")
#> [1] TRUE
time_is_regular(hours, time_by = "hours", allow_gaps = FALSE)
#> [1] FALSE
time_is_regular(hours, time_by = "hours", allow_dups = FALSE)
#> [1] FALSE
# By-group
time_num_gaps(flights$time_hour, g = flights$origin, time_by = "hours")
#> EWR JFK LGA
#> 2489 1820 2468
time_is_regular(flights$time_hour, g = flights$origin, time_by = "hours")
#> EWR JFK LGA
#> FALSE FALSE FALSE
time_expand()
Here we create monthly sequences for each destination that accounts for the start and end dates of each destination
flights %>%
group_by(dest) %>%
time_expand(date, time_by = "month") %>%
summarise(n = n(), start = min(date), end = max(date))
#> # A tibble: 105 × 4
#> dest n start end
#> <chr> <int> <date> <date>
#> 1 ABQ 9 2013-04-22 2013-12-22
#> 2 ACK 6 2013-05-16 2013-10-16
#> 3 ALB 12 2013-01-01 2013-12-01
#> 4 ANC 2 2013-07-06 2013-08-06
#> 5 ATL 12 2013-01-01 2013-12-01
#> 6 AUS 12 2013-01-01 2013-12-01
#> 7 AVL 12 2013-01-01 2013-12-01
#> 8 BDL 12 2013-01-01 2013-12-01
#> 9 BGR 10 2013-03-02 2013-12-02
#> 10 BHM 12 2013-01-02 2013-12-02
#> # ℹ 95 more rows
To create the same grid of months for each dest, we can do the following
flights %>%
time_expand(date, dest, time_by = "month") %>%
summarise(n = n(), start = min(date), end = max(date), .by = dest)
#> # A tibble: 105 × 4
#> dest n start end
#> <chr> <int> <date> <date>
#> 1 ABQ 12 2013-01-01 2013-12-01
#> 2 ACK 12 2013-01-01 2013-12-01
#> 3 ALB 12 2013-01-01 2013-12-01
#> 4 ANC 12 2013-01-01 2013-12-01
#> 5 ATL 12 2013-01-01 2013-12-01
#> 6 AUS 12 2013-01-01 2013-12-01
#> 7 AVL 12 2013-01-01 2013-12-01
#> 8 BDL 12 2013-01-01 2013-12-01
#> 9 BGR 12 2013-01-01 2013-12-01
#> 10 BHM 12 2013-01-01 2013-12-01
#> # ℹ 95 more rows
The ability to create time sequences by group is one of the most powerful features of timeplyr.
flights %>%
time_by(date, "month", as_interval = TRUE) %>%
summarise(across(c(arr_time, dep_time), ~ mean(.x, na.rm = TRUE)))
#> # A tibble: 12 × 3
#> time_intv_month arr_time dep_time
#> <tm_intv> <dbl> <dbl>
#> 1 [2013-01-01, 2013-02-01) 1523. 1347.
#> 2 [2013-02-01, 2013-03-01) 1522. 1348.
#> 3 [2013-03-01, 2013-04-01) 1510. 1359.
#> 4 [2013-04-01, 2013-05-01) 1501. 1353.
#> 5 [2013-05-01, 2013-06-01) 1503. 1351.
#> 6 [2013-06-01, 2013-07-01) 1468. 1351.
#> 7 [2013-07-01, 2013-08-01) 1456. 1353.
#> 8 [2013-08-01, 2013-09-01) 1495. 1350.
#> 9 [2013-09-01, 2013-10-01) 1504. 1334.
#> 10 [2013-10-01, 2013-11-01) 1520. 1340.
#> 11 [2013-11-01, 2013-12-01) 1523. 1344.
#> 12 [2013-12-01, 2014-01-01) 1505. 1357.
Grouped rolling time functions
By-group rolling mean over the last 3 calendar months
eu_stock <- eu_stock %>%
mutate(date = date_decimal(time))
eu_stock %>%
mutate(month_mean = time_roll_mean(value, window = months(3),
time = date,
g = group)) %>%
time_ggplot(date, month_mean, group)
By-group rolling (locf) NA fill
# Prerequisite: Create Time series with missing values
x <- ts(c(NA, 3, 4, NA, 6, NA, NA, 8))
g <- cheapr::seq_id(c(3, 5)) # Two groups of size 3 + 5
.roll_na_fill(x) # Simple locf fill
#> Time Series:
#> Start = 1
#> End = 8
#> Frequency = 1
#> [1] NA 3 4 4 6 6 6 8
roll_na_fill(x, fill_limit = 1) # Fill up to 1 NA
#> Time Series:
#> Start = 1
#> End = 8
#> Frequency = 1
#> [1] NA 3 4 4 6 6 NA 8
roll_na_fill(x, g = g) # Very efficient on large data too
#> Time Series:
#> Start = 1
#> End = 8
#> Frequency = 1
#> [1] NA 3 4 NA 6 6 6 8
year_month
and year_quarter
timeplyr has its own lightweight ‘yearmonth’ and `yearquarter’ classes inspired by the excellent ‘zoo’ and ‘tsibble’ packages.
today <- today()
year_month(today)
#> [1] "2024 Aug"
The underlying data for a year_month
is the number of months since 1 January 1970 (epoch).
unclass(year_month("1970-01-01"))
#> [1] 0
unclass(year_month("1971-01-01"))
#> [1] 12
To create a sequence of ‘year_months’, one can use base arithmetic
year_month(today) + 0:12
#> [1] "2024 Aug" "2024 Sep" "2024 Oct" "2024 Nov" "2024 Dec" "2025 Jan"
#> [7] "2025 Feb" "2025 Mar" "2025 Apr" "2025 May" "2025 Jun" "2025 Jul"
#> [13] "2025 Aug"
year_quarter(today) + 0:4
#> [1] "2024 Q3" "2024 Q4" "2025 Q1" "2025 Q2" "2025 Q3"
time_elapsed()
Let’s look at the time between consecutive flights for a specific flight number
set.seed(42)
flight_201 <- flights %>%
distinct(time_hour, flight) %>%
filter(flight %in% sample(flight, size = 1)) %>%
arrange(time_hour)
tail(sort(table(time_elapsed(flight_201$time_hour, "hours"))))
#>
#> 23 25 48 6 18 24
#> 2 3 4 33 34 218
Flight 201 seems to depart mostly consistently every 24 hours
We can efficiently do the same for all flight numbers
# We use fdistinct with sort as it's much faster and simpler to write
all_flights <- flights %>%
fdistinct(flight, time_hour, sort = TRUE)
all_flights <- all_flights %>%
mutate(elapsed = time_elapsed(time_hour, g = flight, fill = 0))
#> Assuming a time granularity of 1 hour(s)
# Flight numbers with largest relative deviation in time between flights
all_flights %>%
q_summarise(elapsed, .by = flight) %>%
mutate(relative_iqr = p75 / p25) %>%
arrange(desc(relative_iqr))
#> flight p0 p25 p50 p75 p100 relative_iqr
#> <int> <num> <num> <num> <num> <num> <num>
#> 1: 3664 0 12 24 3252.0 6480 271.0000
#> 2: 5709 0 12 24 3080.5 6137 256.7083
#> 3: 513 0 12 24 2250.5 4477 187.5417
#> 4: 3364 0 12 24 2204.5 4385 183.7083
#> 5: 1578 0 24 48 4182.5 8317 174.2708
#> ---
#> 3840: 6114 0 0 0 0.0 0 NaN
#> 3841: 6140 0 0 0 0.0 0 NaN
#> 3842: 6165 0 0 0 0.0 0 NaN
#> 3843: 6171 0 0 0 0.0 0 NaN
#> 3844: 8500 0 0 0 0.0 0 NaN
time_seq_id()
allows us to create unique IDs for regular sequences A new ID is created every time there is a gap in the sequence
flights %>%
select(time_hour) %>%
arrange(time_hour) %>%
mutate(time_id = time_seq_id(time_hour)) %>%
filter(time_id != lag(time_id)) %>%
count(hour(time_hour))
#> Assuming a time granularity of 1 hour(s)
#> # A tibble: 2 × 2
#> `hour(time_hour)` n
#> <int> <int>
#> 1 1 1
#> 2 5 364
We can see that the gaps typically occur at 11pm and the sequence resumes at 5am.
Other convenience functions are included below
calendar()
Easily join common date information to your data
flights_calendar <- flights %>%
select(time_hour) %>%
reframe(calendar(time_hour))
Now that gaps in time have been filled and we have joined our date table, it is easy to count by any time dimension we like
flights_calendar %>%
fcount(isoyear, isoweek)
#> # A tibble: 53 × 3
#> isoyear isoweek n
#> <int> <int> <int>
#> 1 2013 1 5166
#> 2 2013 2 6114
#> 3 2013 3 6034
#> 4 2013 4 6049
#> 5 2013 5 6063
#> 6 2013 6 6104
#> 7 2013 7 6236
#> 8 2013 8 6381
#> 9 2013 9 6444
#> 10 2013 10 6546
#> # ℹ 43 more rows
flights_calendar %>%
fcount(isoweek = iso_week(time))
#> # A tibble: 53 × 2
#> isoweek n
#> <chr> <int>
#> 1 2013-W01 5166
#> 2 2013-W02 6114
#> 3 2013-W03 6034
#> 4 2013-W04 6049
#> 5 2013-W05 6063
#> 6 2013-W06 6104
#> 7 2013-W07 6236
#> 8 2013-W08 6381
#> 9 2013-W09 6444
#> 10 2013-W10 6546
#> # ℹ 43 more rows
flights_calendar %>%
fcount(month_l)
#> # A tibble: 12 × 2
#> month_l n
#> <ord> <int>
#> 1 Jan 27004
#> 2 Feb 24951
#> 3 Mar 28834
#> 4 Apr 28330
#> 5 May 28796
#> 6 Jun 28243
#> 7 Jul 29425
#> 8 Aug 29327
#> 9 Sep 27574
#> 10 Oct 28889
#> 11 Nov 27268
#> 12 Dec 28135
.time_units
See a list of available time units
.time_units
#> [1] "picoseconds" "nanoseconds" "microseconds" "milliseconds" "seconds"
#> [6] "minutes" "hours" "days" "weeks" "months"
#> [11] "years" "fortnights" "quarters" "semesters" "olympiads"
#> [16] "lustrums" "decades" "indictions" "scores" "centuries"
#> [21] "milleniums"
age_years()
Calculate ages (years) accurately
age_years(dmy("28-02-2000"))
#> [1] 24
time_seq()
A lubridate version of seq()
for dates and datetimes
start <- dmy(31012020)
end <- start + years(1)
seq(start, end, by = "month") # Base R version
#> [1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01" "2020-05-31"
#> [6] "2020-07-01" "2020-07-31" "2020-08-31" "2020-10-01" "2020-10-31"
#> [11] "2020-12-01" "2020-12-31" "2021-01-31"
time_seq(start, end, time_by = "month") # lubridate version
#> [1] "2020-01-31" "2020-02-29" "2020-03-31" "2020-04-30" "2020-05-31"
#> [6] "2020-06-30" "2020-07-31" "2020-08-31" "2020-09-30" "2020-10-31"
#> [11] "2020-11-30" "2020-12-31" "2021-01-31"
time_seq()
doesn’t mind mixing dates and datetimes
time_seq(start, as_datetime(end), time_by = "2 weeks")
#> [1] "2020-01-31 UTC" "2020-02-14 UTC" "2020-02-28 UTC" "2020-03-13 UTC"
#> [5] "2020-03-27 UTC" "2020-04-10 UTC" "2020-04-24 UTC" "2020-05-08 UTC"
#> [9] "2020-05-22 UTC" "2020-06-05 UTC" "2020-06-19 UTC" "2020-07-03 UTC"
#> [13] "2020-07-17 UTC" "2020-07-31 UTC" "2020-08-14 UTC" "2020-08-28 UTC"
#> [17] "2020-09-11 UTC" "2020-09-25 UTC" "2020-10-09 UTC" "2020-10-23 UTC"
#> [21] "2020-11-06 UTC" "2020-11-20 UTC" "2020-12-04 UTC" "2020-12-18 UTC"
#> [25] "2021-01-01 UTC" "2021-01-15 UTC" "2021-01-29 UTC"
time_seq_v()
A vectorised version of time_seq()
Currently it is vectorised over from, to and by
# 3 sequences
time_seq_v(from = start,
to = end,
time_by = list("months" = 1:3))
#> [1] "2020-01-31" "2020-02-29" "2020-03-31" "2020-04-30" "2020-05-31"
#> [6] "2020-06-30" "2020-07-31" "2020-08-31" "2020-09-30" "2020-10-31"
#> [11] "2020-11-30" "2020-12-31" "2021-01-31" "2020-01-31" "2020-03-31"
#> [16] "2020-05-31" "2020-07-31" "2020-09-30" "2020-11-30" "2021-01-31"
#> [21] "2020-01-31" "2020-04-30" "2020-07-31" "2020-10-31" "2021-01-31"
# Equivalent to
c(time_seq(start, end, time_by = "month"),
time_seq(start, end, time_by = "2 months"),
time_seq(start, end, time_by = "3 months"))
#> [1] "2020-01-31" "2020-02-29" "2020-03-31" "2020-04-30" "2020-05-31"
#> [6] "2020-06-30" "2020-07-31" "2020-08-31" "2020-09-30" "2020-10-31"
#> [11] "2020-11-30" "2020-12-31" "2021-01-31" "2020-01-31" "2020-03-31"
#> [16] "2020-05-31" "2020-07-31" "2020-09-30" "2020-11-30" "2021-01-31"
#> [21] "2020-01-31" "2020-04-30" "2020-07-31" "2020-10-31" "2021-01-31"
time_seq_sizes()
Vectorised function that calculates time sequence lengths
seq_lengths <- time_seq_sizes(start, start + days(c(1, 10, 20)),
time_by = list("days" = c(1, 5, 10)))
seq_lengths
#> [1] 2 3 3
# Use time_seq_v2() if you know the sequence lengths
seqs <- time_seq_v2(seq_lengths, start, time_by = list("days" = c(1, 5, 10)))
seqs
#> [1] "2020-01-31" "2020-02-01" "2020-01-31" "2020-02-05" "2020-02-10"
#> [6] "2020-01-31" "2020-02-10" "2020-02-20"
Dealing with impossible dates and datetimes is very simple
time_seq(start, end, time_by = "month", roll_month = "postday") # roll impossible months forward
#> [1] "2020-01-31" "2020-03-01" "2020-03-31" "2020-05-01" "2020-05-31"
#> [6] "2020-07-01" "2020-07-31" "2020-08-31" "2020-10-01" "2020-10-31"
#> [11] "2020-12-01" "2020-12-31" "2021-01-31"
time_seq(start, end, time_by = "month", roll_month = "NA") # no roll
#> [1] "2020-01-31" NA "2020-03-31" NA "2020-05-31"
#> [6] NA "2020-07-31" "2020-08-31" NA "2020-10-31"
#> [11] NA "2020-12-31" "2021-01-31"
time_seq(start, end, time_by = dmonths(1)) # lubridate version with durations
#> [1] "2020-01-31 00:00:00 UTC" "2020-03-01 10:30:00 UTC"
#> [3] "2020-03-31 21:00:00 UTC" "2020-05-01 07:30:00 UTC"
#> [5] "2020-05-31 18:00:00 UTC" "2020-07-01 04:30:00 UTC"
#> [7] "2020-07-31 15:00:00 UTC" "2020-08-31 01:30:00 UTC"
#> [9] "2020-09-30 12:00:00 UTC" "2020-10-30 22:30:00 UTC"
#> [11] "2020-11-30 09:00:00 UTC" "2020-12-30 19:30:00 UTC"
#> [13] "2021-01-30 06:00:00 UTC"
iso_week()
Simple function to get formatted ISO weeks.
iso_week(today())
#> [1] "2024-W33"
iso_week(today(), day = TRUE)
#> [1] "2024-W33-6"
iso_week(today(), year = FALSE)
#> [1] "W33"
time_cut()
Create pretty time axes using time_breaks()
times <- flights$time_hour
dates <- flights$date
date_breaks <- time_breaks(dates, n = 12)
time_breaks <- time_breaks(times, n = 12, time_floor = TRUE)
weekly_data <- flights %>%
time_by(time = date, time_by = "week",
to = max(time_span(date, time_by = "week")),
.name = "date") %>%
count()
weekly_data %>%
ggplot(aes(x = interval_start(date), y = n)) +
geom_bar(stat = "identity", fill = "#0072B2") +
scale_x_date(breaks = date_breaks, labels = scales::label_date_short())
flights %>%
ggplot(aes(x = time_hour)) +
geom_bar(fill = "#0072B2") +
scale_x_datetime(breaks = time_breaks, labels = scales::label_date_short())