Nothing
test_that("gapless_Datetimes works", {
dataset <-
tibble::tibble(Id = c("A", "A", "A", "B", "B", "B"),
Datetime = lubridate::as_datetime(1) +
lubridate::days(c(0:2, 4, 6, 8)))
expect_equal(dataset %>%
dplyr::group_by(Id) %>%
gapless_Datetimes() %>% nrow(),
6)
expect_equal(dataset %>%
dplyr::group_by(Id) %>%
gapless_Datetimes(epoch = "1 day") %>% nrow(),
8)
expect_equal(dataset %>%
gapless_Datetimes() %>% nrow(),
5)
expect_equal(dataset %>%
gapless_Datetimes(epoch = "1 day") %>% nrow(),
9)
expect_equal(dataset %>%
gapless_Datetimes(epoch = "1 day") %>% ncol(),
1)
expect_equal(dataset %>%
dplyr::group_by(Id) %>%
gapless_Datetimes(epoch = "1 day") %>% ncol(),
2)
})
test_that("gapless_Datetimes throws appropriate errors", {
dataset <-
tibble::tibble(Id = c("A", "A", "A", "B", "B", "B"),
Datetime = lubridate::as_datetime(1) +
lubridate::days(c(0:2, 4, 6, 8)))
expect_error(dataset$Id %>% gapless_Datetimes(),
"dataset is not a dataframe")
expect_error(dataset %>% gapless_Datetimes(Datetime.colname = Status),
"Datetime.colname must be part of the dataset")
expect_error(dataset %>% gapless_Datetimes(Datetime.colname = Id),
"Datetime.colname must be a Datetime")
expect_error(dataset %>% gapless_Datetimes(epoch = 5),
"epoch must either be a duration or a string")
})
test_that("gap_handler works", {
dataset <-
tibble::tibble(Id = c("A", "A", "A", "B", "B", "B"),
Datetime = lubridate::as_datetime(1) +
lubridate::days(c(0:2, 4, 6, 8)) +
lubridate::hours(c(0,12,rep(0,4))))
expect_equal(dataset %>% gap_handler(epoch = "1 day") %>% dim(),c(10,3))
expect_equal(dataset %>%
gap_handler(epoch = "1 day", behavior = "irregulars") %>%
dim(),c(1,3))
expect_equal(dataset %>%
gap_handler(epoch = "1 day", behavior = "gaps") %>% dim(),
c(4,1))
expect_equal(dataset %>%
gap_handler(epoch = "1 day", behavior = "regulars") %>% dim(),
c(5,3))
expect_equal(dataset %>% dplyr::group_by(Id) %>%
gap_handler(epoch = "1 day") %>% dim(),c(9,3))
expect_equal(dataset %>% dplyr::group_by(Id) %>%
gap_handler(epoch = "1 day", behavior = "irregulars") %>%
dim(),c(1,3))
expect_equal(dataset %>% dplyr::group_by(Id) %>%
gap_handler(epoch = "1 day", behavior = "gaps") %>% dim(),
c(3,2))
expect_equal(dataset %>% dplyr::group_by(Id) %>%
gap_handler(epoch = "1 day", behavior = "regulars") %>% dim(),
c(5,3))
})
test_that("gapless_Datetimes throws appropriate errors", {
dataset <-
tibble::tibble(Id = c("A", "A", "A", "B", "B", "B"),
Datetime = lubridate::as_datetime(1) +
lubridate::days(c(0:2, 4, 6, 8)))
expect_error(dataset$Id %>% gap_handler(),
"dataset is not a dataframe")
expect_error(dataset %>% gap_handler(Datetime.colname = Status),
"Datetime.colname must be part of the dataset")
expect_error(dataset %>% gap_handler(Datetime.colname = Id),
"Datetime.colname must be a Datetime")
expect_error(dataset %>% gap_handler(epoch = 5),
"epoch must either be a duration or a string")
expect_error(dataset %>% gap_handler(behavior = "foo"),
"'arg' should be one of ")
})
test_that("gap_finder works", {
dataset <-
tibble::tibble(Id = c("A", "A", "A", "B", "B", "B"),
Datetime = lubridate::as_datetime(1) +
lubridate::days(c(0:2, 4, 6, 8)) +
lubridate::hours(c(0,12,rep(0,4)))) %>%
dplyr::group_by(Id)
expect_equal(gap_finder(dataset, gap.data = TRUE, silent = TRUE) %>%
dim(),c(2,3))
testthat::expect_message(gap_finder(dataset),
regexp = "Found 2 gaps. 6 Datetimes fall into the regular sequence.")
testthat::expect_message(gap_finder(dataset, epoch = "1 day"),
regexp = "Found 3 gaps. 5 Datetimes fall into the regular sequence.")
})
#-----------
test_that("has_gaps works with ungrouped data", {
# No gaps
data_no_gaps <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(0:5)
)
expect_false(has_gaps(data_no_gaps, epoch = "1 hour"))
# With gaps
data_with_gaps <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 3, 5)) # gap between 1 and 3, 3 and 5
)
expect_true(has_gaps(data_with_gaps, epoch = "1 hour"))
# Custom Datetime column name
data_custom_dt <- tibble::tibble(
MyTime = lubridate::as_datetime(0) + lubridate::days(c(0, 2))
)
expect_true(has_gaps(data_custom_dt, Datetime.colname = MyTime, epoch = "1 day"))
})
test_that("has_gaps works with grouped data", {
# No gaps within groups
data_grouped_no_gaps <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::minutes(c(0:2, 0:2))
) %>% dplyr::group_by(Id)
expect_false(has_gaps(data_grouped_no_gaps, epoch = "1 min"))
# Gaps in one group
data_grouped_gaps_one <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::minutes(c(0, 1, 3, 0, 1, 2)) # gap in A
) %>% dplyr::group_by(Id)
expect_true(has_gaps(data_grouped_gaps_one, epoch = "1 min"))
# Gaps in all groups
data_grouped_gaps_all <- tibble::tibble(
Id = rep(c("A", "B"), each = 4),
Datetime = lubridate::as_datetime(0) + lubridate::minutes(c(0, 2, 4, 8, 10, 12, 14, 18)) # gaps in A and B
) %>% dplyr::group_by(Id)
expect_true(has_gaps(data_grouped_gaps_all, epoch = "2 mins"))
# Groups span unconnected parts - considered a gap by default epoch
data_unconnected_groups <- tibble::tibble(
State = c("X", "X", "Y", "Y", "X", "X"),
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 10, 11, 20, 21))
) %>% dplyr::group_by(State)
# dominant epoch for X will be 1 hour, but there's a large jump
# dominant epoch for Y will be 1 hour.
expect_true(has_gaps(data_unconnected_groups))
# Single observation in a group
dataset_single_obs_group <- tibble::tibble(
Id = c("A", "A", "B"),
Datetime = lubridate::as_datetime(0) + lubridate::days(c(0, 1, 0))
) %>% dplyr::group_by(Id)
# Group B has only one observation, gap_handler filters it out, so no gaps reported for it.
# Group A has no gaps.
expect_false(has_gaps(dataset_single_obs_group, epoch = "1 day"))
dataset_single_obs_group_with_gap <- tibble::tibble(
Id = c("A", "A", "B", "A"),
Datetime = lubridate::as_datetime(0) + lubridate::days(c(0, 2, 0, 3)) # A: 0,2,3 (gap); B: 0
) %>% dplyr::group_by(Id)
expect_true(has_gaps(dataset_single_obs_group_with_gap, epoch = "1 day"))
})
test_that("has_gaps handles epoch correctly", {
data <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::days(c(0, 2, 3)) # gap if epoch is 1 day
)
expect_true(has_gaps(data, epoch = "1 day"))
expect_true(has_gaps(data, epoch = "dominant.epoch"))
data2 <- tibble::tibble(Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0,2,4)))
expect_false(has_gaps(data2, epoch = "2 hours"))
expect_true(has_gaps(data2, epoch = "1 hour"))
expect_false(has_gaps(data2, epoch = lubridate::duration(2, "hours")))
})
test_that("has_gaps error handling", {
expect_error(has_gaps(list()), "dataset is not a dataframe")
data <- tibble::tibble(D = lubridate::as_datetime(0))
expect_error(has_gaps(data, Datetime.colname = NotDatetime), "Datetime.colname must be part of the dataset")
data_wrong_type <- tibble::tibble(Datetime = 1:3)
expect_error(has_gaps(data_wrong_type), "Datetime.colname must be a Datetime")
data_ok <- tibble::tibble(Datetime = lubridate::as_datetime(0))
expect_error(has_gaps(data_ok, epoch = 123), "epoch must either be a duration or a string")
})
# Tests for has_irregulars
test_that("has_irregulars works with ungrouped data", {
# No irregulars
data_no_irregulars <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(0:5)
)
expect_false(has_irregulars(data_no_irregulars, epoch = "1 hour"))
# With irregulars
data_with_irregulars <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::dhours(c(0, 1.5, 2, 3.1, 4))
)
expect_true(has_irregulars(data_with_irregulars, epoch = "1 hour"))
# Custom Datetime column name
data_custom_dt <- tibble::tibble(
MyTime = lubridate::as_datetime(0) + lubridate::ddays(c(0, 1.2, 2))
)
expect_true(has_irregulars(data_custom_dt, Datetime.colname = MyTime, epoch = "1 day"))
})
test_that("has_irregulars works with grouped data", {
# No irregulars within groups
data_grouped_no_irregulars <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::minutes(c(0:2, 10:12))
) %>% dplyr::group_by(Id)
expect_false(has_irregulars(data_grouped_no_irregulars, epoch = "1 min"))
# Irregulars in one group
data_grouped_irregulars_one <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::dminutes(c(0, 1.5, 2, 10, 11, 12)) # irregular in A
) %>% dplyr::group_by(Id)
expect_true(has_irregulars(data_grouped_irregulars_one, epoch = "1 min"))
# Irregulars in all groups
data_grouped_irregulars_all <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::dminutes(c(0, 2.2, 4, 10.1, 12, 14.9))
) %>% dplyr::group_by(Id)
expect_true(has_irregulars(data_grouped_irregulars_all, epoch = "2 mins"))
# Single observation in a group (cannot be irregular by itself with gapless_Datetimes current logic)
dataset_single_obs_group <- tibble::tibble(
Id = c("A", "A", "B"),
Datetime = lubridate::as_datetime(0) + lubridate::ddays(c(0, 1, 0.5)) # B has 0.5
) %>% dplyr::group_by(Id)
# Group B will be filtered by gapless_Datetimes, but remains in the output of gap_handler. Group A is regular.
expect_true(has_irregulars(dataset_single_obs_group, epoch = "1 day"))
dataset_single_obs_group_irreg <- tibble::tibble(
Id = c("A", "A", "B", "A"),
Datetime = lubridate::as_datetime(0) + lubridate::ddays(c(0, 1.5, 0, 2)) # A: 0, 1.5, 2 (1.5 is irreg); B: 0
) %>% dplyr::group_by(Id)
# Group B is filtered by gapless_Datetimes. Group A has 1.5 which is irregular.
expect_true(has_irregulars(dataset_single_obs_group_irreg, epoch = "1 day"))
})
test_that("has_irregulars handles epoch correctly", {
data <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::dhours(c(0, 1, 2.5, 4)) # 2.5 is irregular if epoch is 1 hour
)
expect_true(has_irregulars(data, epoch = "1 hour"))
expect_false(has_irregulars(data, epoch = "30 mins")) # 0,1,2.5,4 -> 0, 60, 150, 240 mins. All are multiples of 30min
expect_true(has_irregulars(data, epoch = lubridate::duration(1, "hour")))
data2 <- tibble::tibble(Datetime = lubridate::as_datetime(0) + lubridate::dhours(c(0,2,4.1)))
expect_true(has_irregulars(data2, epoch = "2 hours")) # 4.1 is irregular
expect_true(has_irregulars(data2, epoch = "1 hour")) # 4.1 is irregular
})
test_that("has_irregulars error handling", {
expect_error(has_irregulars(list()), "dataset is not a dataframe")
data <- tibble::tibble(D = lubridate::as_datetime(0))
expect_error(has_irregulars(data, Datetime.colname = NotDatetime), "Datetime.colname must be part of the dataset")
data_wrong_type <- tibble::tibble(Datetime = 1:3)
expect_error(has_irregulars(data_wrong_type), "Datetime.colname must be a Datetime")
data_ok <- tibble::tibble(Datetime = lubridate::as_datetime(0))
expect_error(has_irregulars(data_ok, epoch = 123), "epoch must either be a duration or a string")
})
# Tests for extract_gaps
test_that("extract_gaps handles implicit gaps correctly (no Variable.colname)", {
# No gaps
data_no_gaps <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(0:2)
)
expect_message(result_no_gaps <- extract_gaps(data_no_gaps, epoch = "1 hour", full.days = FALSE), "No implicit gaps found")
expect_equal(nrow(result_no_gaps), 0)
# One gap
data_one_gap <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 2)) # gap at 1 hour
)
result_one_gap <- extract_gaps(data_one_gap, epoch = "1 hour", full.days = FALSE)
expect_equal(nrow(result_one_gap), 1)
expect_equal(result_one_gap$gap.id, 1)
expect_equal(result_one_gap$start, lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_one_gap$end, lubridate::as_datetime(0) + lubridate::hours(1) + lubridate::duration(30, "minutes"))
expect_equal(result_one_gap$duration, lubridate::duration(1, "hour"))
# Multiple gaps
data_multi_gaps <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 3, 4, 7)) # gaps at 1,2 and 5,6
)
result_multi_gaps <- extract_gaps(data_multi_gaps, epoch = "1 hour", full.days = FALSE)
expect_equal(nrow(result_multi_gaps), 2)
expect_equal(result_multi_gaps$gap.id, c(1, 2))
expect_equal(result_multi_gaps$start[1], lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_multi_gaps$end[1], lubridate::as_datetime(0) + lubridate::hours(2) + lubridate::duration(30, "minutes"))
expect_equal(result_multi_gaps$duration[1], lubridate::duration(2, "hours"))
expect_equal(result_multi_gaps$start[2], lubridate::as_datetime(0) + lubridate::hours(5) - lubridate::duration(30, "minutes"))
expect_equal(result_multi_gaps$end[2], lubridate::as_datetime(0) + lubridate::hours(6) + lubridate::duration(30, "minutes"))
expect_equal(result_multi_gaps$duration[2], lubridate::duration(2, "hours"))
# full.days = TRUE
data_fd <- tibble::tibble(Datetime = lubridate::as_datetime("2023-01-01 10:00:00") + lubridate::days(c(0,2))) # gap on 2023-01-02
res_fd <- extract_gaps(data_fd, epoch="10 hours", full.days = TRUE)
expect_equal(nrow(res_fd), 3)
expect_equal(res_fd$start[1], lubridate::as_datetime("2023-01-01 00:00:00") - lubridate::duration(5, "hours"))
expect_equal(res_fd$end[1],lubridate::as_datetime("2023-01-01 00:00:00") + lubridate::duration(5, "hours")) # seq creates end of day, then + epoch/2
})
test_that("extract_gaps handles explicit gaps (with Variable.colname)", {
# No NA, no implicit gaps
data_no_na_no_implicit <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(0:2),
Value = c(10, 20, 30)
)
expect_message(result_no_na <- extract_gaps(data_no_na_no_implicit, Value, epoch = "1 hour", include.implicit.gaps = FALSE, full.days=FALSE), "No gaps found")
expect_equal(nrow(result_no_na), 0)
# Has NA, no implicit gaps
data_has_na_no_implicit <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(0:3),
Value = c(10, NA, NA, 40)
)
expect_warning( # due to include.implicit.gaps = FALSE and has_gaps being false
result_has_na <- extract_gaps(data_has_na_no_implicit, Value, epoch = "1 hour", include.implicit.gaps = FALSE, full.days=FALSE),
NA # No warning because no implicit gaps
)
expect_equal(nrow(result_has_na), 1)
expect_equal(result_has_na$gap.id, 1)
expect_equal(result_has_na$start, lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes")) # epoch/2 before first NA
expect_equal(result_has_na$end, lubridate::as_datetime(0) + lubridate::hours(2) + lubridate::duration(30, "minutes")) # epoch/2 after last NA
expect_equal(result_has_na$duration, lubridate::duration(2, "hours"))
# No NA, but has implicit gaps, include.implicit.gaps = TRUE
data_no_na_has_implicit_true <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 2)), # implicit gap at 1h
Value = c(10, 30)
)
result_implicit_true <- extract_gaps(data_no_na_has_implicit_true, Value, epoch = "1 hour", include.implicit.gaps = TRUE, full.days=FALSE)
# gap_handler adds Datetime at 1h, Value is NA. This is one gap.
expect_equal(nrow(result_implicit_true), 1)
expect_equal(result_implicit_true$gap.id, 1)
expect_equal(result_implicit_true$start, lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_implicit_true$end, lubridate::as_datetime(0) + lubridate::hours(1) + lubridate::duration(30, "minutes"))
expect_equal(result_implicit_true$duration, lubridate::duration(1, "hour"))
# No NA, but has implicit gaps, include.implicit.gaps = FALSE
data_no_na_has_implicit_false <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 2)), # implicit gap at 1h
Value = c(10, 30)
)
expect_warning(
expect_message(
result_implicit_false <- extract_gaps(data_no_na_has_implicit_false, Value, epoch = "1 hour", include.implicit.gaps = FALSE, full.days=FALSE)),
"There are implicit gaps in the dataset that will not be part of the extracted summary"
)
expect_equal(nrow(result_implicit_false), 0)
# Has NA AND implicit gaps, include.implicit.gaps = TRUE
data_na_and_implicit_true <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 3, 5)), # implicit gap at 2h, 4h
Value = c(10, NA, 30, NA) # NA at 1h (explicit), NA at 5h (explicit)
) # After gap_handler: DTs: 0,1,2,3,4,5; Vals: 10,NA,NA(implicit),30,NA(implicit),NA
# Gaps: (1h, 2h), (4h, 5h)
result_na_implicit_true <- extract_gaps(data_na_and_implicit_true, Value, epoch = "1 hour", include.implicit.gaps = TRUE, full.days=FALSE)
expect_equal(nrow(result_na_implicit_true), 2)
expect_equal(result_na_implicit_true$gap.id, c(1,2))
# Gap 1: Dts 1h (NA), 2h (implicit NA)
expect_equal(result_na_implicit_true$start[1], lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_true$end[1], lubridate::as_datetime(0) + lubridate::hours(2) + lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_true$duration[1], lubridate::duration(2, "hours"))
# Gap 2: Dts 4h (implicit NA), 5h (NA)
expect_equal(result_na_implicit_true$start[2], lubridate::as_datetime(0) + lubridate::hours(4) - lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_true$end[2], lubridate::as_datetime(0) + lubridate::hours(5) + lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_true$duration[2], lubridate::duration(2, "hours"))
# Has NA AND implicit gaps, include.implicit.gaps = FALSE
data_na_and_implicit_false <- tibble::tibble(
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 3, 5)), # implicit gap at 2h, 4h
Value = c(10, NA, 30, NA) # NA at 1h, NA at 5h
)
expect_warning(
result_na_implicit_false <- extract_gaps(data_na_and_implicit_false, Value, epoch = "1 hour", include.implicit.gaps = FALSE, full.days=FALSE),
"There are implicit gaps in the dataset that will not be part of the extracted summary"
)
# Only considers original NAs at 1h and 5h. These are separate gaps as per extract_states logic on original data.
expect_equal(nrow(result_na_implicit_false), 2)
expect_equal(result_na_implicit_false$gap.id, c(1,2))
expect_equal(result_na_implicit_false$start[1], lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_false$end[1], lubridate::as_datetime(0) + lubridate::hours(1) + lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_false$duration[1], lubridate::duration(1, "hour"))
expect_equal(result_na_implicit_false$start[2], lubridate::as_datetime(0) + lubridate::hours(5) - lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_false$end[2], lubridate::as_datetime(0) + lubridate::hours(5) + lubridate::duration(30, "minutes"))
expect_equal(result_na_implicit_false$duration[2], lubridate::duration(1, "hour"))
})
test_that("extract_gaps works with grouped data", {
# Implicit gaps, grouped
data_grouped_implicit <- tibble::tibble(
Id = rep(c("A", "B"), each = 2),
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 2, 10, 12)) # gap at 1h for A, 11h for B
) %>% dplyr::group_by(Id)
result_grp_implicit <- extract_gaps(data_grouped_implicit, epoch = "1 hour", full.days = FALSE)
expect_equal(nrow(result_grp_implicit), 2)
expect_equal(result_grp_implicit$Id, c("A", "B"))
expect_equal(result_grp_implicit$gap.id, c(1, 1)) # gap.id is per group here
expect_equal(result_grp_implicit$start[result_grp_implicit$Id=="A"], lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(result_grp_implicit$duration[result_grp_implicit$Id=="A"], lubridate::duration(1, "hour"))
expect_equal(result_grp_implicit$start[result_grp_implicit$Id=="B"], lubridate::as_datetime(0) + lubridate::hours(11) - lubridate::duration(30, "minutes"))
expect_equal(result_grp_implicit$duration[result_grp_implicit$Id=="B"], lubridate::duration(1, "hour"))
# Explicit gaps, grouped, include.implicit.gaps = TRUE
data_grouped_explicit_implicit_T <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 3, 10, 12, 13)), # A implicit at 2h; B implicit at 11h
Value = c(1, NA, 3, 10, NA, 30) # A explicit NA at 1h; B explicit NA at 12h
) %>% dplyr::group_by(Id)
# For A: gap_handler DTs: 0,1,2,3; Vals: 1,NA,NA(impl),3 -> Gaps at 1h,2h
# For B: gap_handler DTs: 10,11,12,13; Vals: 10,NA(impl),NA,30 -> Gaps at 11h,12h
result_grp_exp_impl_T <- extract_gaps(data_grouped_explicit_implicit_T, Value, epoch = "1 hour", include.implicit.gaps = TRUE, full.days = FALSE)
expect_equal(nrow(result_grp_exp_impl_T), 2) # One combined gap per group
expect_equal(result_grp_exp_impl_T$Id, c("A", "B"))
expect_equal(result_grp_exp_impl_T$gap.id, c(1,1))
# Check A's gap (1h explicit, 2h implicit)
res_A <- dplyr::filter(result_grp_exp_impl_T, Id == "A")
expect_equal(res_A$start, lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(res_A$end, lubridate::as_datetime(0) + lubridate::hours(2) + lubridate::duration(30, "minutes"))
expect_equal(res_A$duration, lubridate::duration(2, "hours"))
# Check B's gap (11h implicit, 12h explicit)
res_B <- dplyr::filter(result_grp_exp_impl_T, Id == "B")
expect_equal(res_B$start, lubridate::as_datetime(0) + lubridate::hours(11) - lubridate::duration(30, "minutes"))
expect_equal(res_B$end, lubridate::as_datetime(0) + lubridate::hours(12) + lubridate::duration(30, "minutes"))
expect_equal(res_B$duration, lubridate::duration(2, "hours"))
# Explicit gaps, grouped, include.implicit.gaps = FALSE
data_grouped_explicit_implicit_F <- tibble::tibble(
Id = rep(c("A", "B"), each = 3),
Datetime = lubridate::as_datetime(0) + lubridate::hours(c(0, 1, 3, 10, 12, 13)), # A implicit at 2h; B implicit at 11h
Value = c(1, NA, 3, 10, NA, 30) # A explicit NA at 1h; B explicit NA at 12h
) %>% dplyr::group_by(Id)
expect_warning(
result_grp_exp_impl_F <- extract_gaps(data_grouped_explicit_implicit_F, Value, epoch = "1 hour", include.implicit.gaps = FALSE, full.days = FALSE),
"There are implicit gaps in the dataset that will not be part of the extracted summary"
)
# Only original NAs considered.
# For A: NA at 1h
# For B: NA at 12h
expect_equal(nrow(result_grp_exp_impl_F), 2)
expect_equal(result_grp_exp_impl_F$Id, c("A", "B"))
expect_equal(result_grp_exp_impl_F$gap.id, c(1,1)) # gap.id is per group here
res_A_F <- dplyr::filter(result_grp_exp_impl_F, Id == "A")
expect_equal(res_A_F$start, lubridate::as_datetime(0) + lubridate::hours(1) - lubridate::duration(30, "minutes"))
expect_equal(res_A_F$end, lubridate::as_datetime(0) + lubridate::hours(1) + lubridate::duration(30, "minutes"))
expect_equal(res_A_F$duration, lubridate::duration(1, "hour"))
res_B_F <- dplyr::filter(result_grp_exp_impl_F, Id == "B")
expect_equal(res_B_F$start, lubridate::as_datetime(0) + lubridate::hours(12) - lubridate::duration(30, "minutes"))
expect_equal(res_B_F$end, lubridate::as_datetime(0) + lubridate::hours(12) + lubridate::duration(30, "minutes"))
expect_equal(res_B_F$duration, lubridate::duration(1, "hour"))
# Single observation in one group (filtered out by gap_finder if no Variable.colname)
dataset_single_obs_group <- tibble::tibble(
Id = c("A", "A", "B", "A"),
Datetime = lubridate::as_datetime(0) + lubridate::days(c(0, 2, 0, 3)), # A: 0,2,3 (gap at day 1); B: 0
Value = c(1,2,10,3)
) %>% dplyr::group_by(Id)
res_single_implicit <- extract_gaps(dataset_single_obs_group, epoch = "1 day", full.days=FALSE) # No Variable.colname
# Group B is filtered by gapless_Datetimes.
# Group A has gap at day 1.
expect_equal(nrow(res_single_implicit), 1)
expect_equal(res_single_implicit$Id, "A")
expect_equal(res_single_implicit$start, lubridate::as_datetime(0) + lubridate::days(1) - lubridate::duration(12, "hours"))
res_single_explicit <- extract_gaps(dataset_single_obs_group, Value, epoch = "1 day", include.implicit.gaps = TRUE, full.days=FALSE)
# gap_handler for A: DTs 0,1,2,3; Vals 1,NA,2,3. Gap for A at day 1.
# gap_handler for B: DT 0; Val 10. No gaps for B.
expect_equal(nrow(res_single_explicit), 1)
expect_equal(res_single_explicit$Id, "A")
expect_equal(res_single_explicit$start, lubridate::as_datetime(0) + lubridate::days(1) - lubridate::duration(12, "hours"))
expect_equal(res_single_explicit$duration, lubridate::duration(1, "day"))
})
test_that("extract_gaps error handling", {
expect_error(extract_gaps(list()), "dataset is not a dataframe")
data <- tibble::tibble(D = lubridate::as_datetime(0), V = 1)
expect_error(extract_gaps(data, Datetime.colname = NotDatetime), "Datetime.colname must be part of the dataset")
data_wrong_type <- tibble::tibble(Datetime = 1:3, V=1)
expect_error(extract_gaps(data_wrong_type), "Datetime.colname must be a Datetime")
data_ok <- tibble::tibble(Datetime = lubridate::as_datetime(0), V=1)
expect_error(extract_gaps(data_ok, epoch = 123), "epoch must either be a duration or a string")
expect_error(extract_gaps(data_ok, Variable.colname = NotValue), "Variable.colname must be part of the dataset")
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.