-
Notifications
You must be signed in to change notification settings - Fork 0
/
reframe_events.R
90 lines (85 loc) · 2.83 KB
/
reframe_events.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#' Reframe event intervals to calendar units
#'
#' `r lifecycle::badge("experimental")`
#'
#' Convert rows of events to sequence of calendar units for plotting.
#' Duplicates all columns except for `event_start` and `event_date`.
#' Requires a unique id key for each event.
#'
#' This is a thin wrapper around `dplyr::reframe()` that expands
#' each uniquely identified event in `.data` to a sequence of datetimes defined
#' by the `start`, `end` and the interval `cal_unit`.
#'
#' @param .data A data frame or tibble containing event details
#' @param event_start column containing event start date
#' @param event_end column containing event end date
#' @param id_cols (optional) set of columns that uniquely identify each observation.
#' Ignored if `.data` is grouped (i.e. using \link[dplyr]{group_by}).
#' If `.data` is not grouped and `id_cols` is `NULL`, all columns except for
#' `event_start` and `event_end` are used.
#' @inheritParams make_empty_units
#'
#' @return See return value of \link[dplyr]{reframe}
#' @export
#' @importFrom dplyr group_by pick filter n group_vars
#'
#' @examples
#' event <- data.frame(
#' id = 1,
#' start = as.Date("2024-01-05"),
#' end = as.Date("2024-01-10")
#' )
#' reframe_events(event, start, end)
#' demo_events_gpt |>
#' reframe_events(startDate, endDate)
reframe_events <- function(
.data, event_start, event_end, id_cols = NULL,
dates_to = "unit_date", cal_unit = "day") {
if (dplyr::is_grouped_df(.data)) {
x_grpd <- .data
} else if (!is.null(id_cols)) {
x_grpd <- .data |>
dplyr::group_by(pick({{ id_cols }}))
} else {
interval_vars <- sapply(enquos(event_start, event_end), as_name)
grouping_vars <- setdiff(names(.data), interval_vars)
if (length(grouping_vars) == 0) {
cli::cli_abort(c(
"No columns available for `id_cols`",
"x" = "`.data` should have at least one extra column
other than `start` and `end`"
))
}
x_grpd <- .data |>
dplyr::group_by(pick(tidyselect::all_of(grouping_vars)))
}
# check for dups (otherwise reframe will throw an error)
dups <- x_grpd |> dplyr::filter(n() > 1)
if (nrow(dups) != 0) {
grouping_vars <- dplyr::group_vars(x_grpd)
cli::cli_abort(c("Rows must be uniquely identified.",
"i" = "Column{?s} {.var {grouping_vars}} do{?es/} not uniquely identify rows.",
"i" = "Modify `id_cols`."
))
}
x_grpd |>
dplyr::reframe(
unit_date = seq({{ event_start }}, {{ event_end }}, by = cal_unit)
)
}
if (FALSE) {
# missing id columns
library(dplyr)
demo_events(30) |>
select(start, end) |>
rowwise() |>
reframe_events(start, end)
demo_events(30) |>
select(start, end) |>
mutate(id = "same") |>
reframe_events(start, end)
demo_events(30) |>
select(start, end) |>
mutate(id = "same", id2 = "same") |>
reframe_events(start, end)
}