H21 Prepare numerator and denominator
Use your current course session. Preparation and course runner · R script ↓
H21a Define the period and population
Goal: State the business meaning before calculating.
Prerequisites: H20.
Teaching convention: August 2026. The denominator is policies active on August 1. The numerator is cancellations among those policies after August 1 and through August 31 inclusive. A policy already terminated on August 1 is excluded. New business during August is excluded. This is a simplified teaching definition.
training_step(
"H21a",
{
dated_policies <- selected_rows
dated_policies$start_date <- as.Date(rep("2026-01-01", 6))
dated_policies$cancel_date <- as.Date(c(NA, NA, "2026-08-15", NA, NA, NA))
period_start <- as.Date("2026-08-01")
period_end <- as.Date("2026-08-31")
print(dated_policies)
},
needs = c("H20")
)Expected result: Six policies in the opening population and one cancellation date.
Task: Why is cancelled alone insufficient?
Show solution
Without a date, the period of the cancellation is unknown.
H21 Prepare numerator and denominator
Goal: Calculate two explicit indicators.
Prerequisites: H21a.
The recipe makes business logic visible before defining a metric. Its output has a dedicated contract.
training_step(
"H21",
{
cohort_recipe <- dr_recipe() |>
dr_step_mutate(
in_opening = start_date <= period_start &
(is.na(cancel_date) | cancel_date > period_start)
) |>
dr_step_mutate(
in_cancellations = in_opening &
!is.na(cancel_date) &
cancel_date <= period_end
)
cohort_contract <- dr_contract(
"cohort",
c(
policy_id = "integer",
premium = "numeric",
cancelled = "logical",
customer_id = "integer",
broker_id = "integer",
start_date = "Date",
cancel_date = "Date",
in_opening = "logical",
in_cancellations = "logical"
),
key = "policy_id"
) |>
dr_contract_policy(
required = c(
"policy_id",
"premium",
"customer_id",
"broker_id",
"start_date",
"in_opening",
"in_cancellations"
)
)
cohort_product <- dr_product(
"policies.cohort",
dated_policies,
contract = cohort_contract
) |>
dr_add_recipe(cohort_recipe) |>
dr_add_quality(list(nonempty_denominator = ~ sum(in_opening) > 0))
cohort_run <- dr_run(cohort_product, write = FALSE)
cohort_rows <- dr_collect(cohort_run)
stopifnot(
sum(cohort_rows$in_opening) == 6L,
sum(cohort_rows$in_cancellations) == 1L
)
},
needs = c("H21a")
)Expected result: Denominator 6 and numerator 1. cancel_date may be missing for ongoing policies.
Task: What happens to a policy starting on August 10?
Show solution
in_opening is FALSE. Try it in a copy and preserve the original data.