Match event dates, such as claim dates or inspection dates, to policy records that were active when the event occurred. The matched result contains the portfolio characteristics and coverage information applicable on each event date.
Arguments
- portfolio
A
data.frameordata.tablewith portfolio rows and active date intervals.- dates
A
data.frameordata.tablewith event or snapshot dates.- period_start
Character string. Name of the portfolio column with period start dates.
- period_end
Character string. Name of the portfolio column with period end dates.
- date
Character string. Name of the date column in
dates.- by
Character vector with additional columns used to match
portfolioanddates, for example policy number or claim identifier.- unmatched
Character string. Use
"drop"to omit event dates for which no active portfolio row is found, or"keep"to retain them with missing portfolio information. The default is"drop".- multiple_matches
Character string controlling events that match multiple active portfolio rows. Use
"all"to retain every match, or"first"or"last"to retain one matching row. The default is"all".- nomatch, mult
Deprecated technical argument names. Use
unmatchedandmultiple_matchesinstead.
Value
A regular data.frame containing the event records and the portfolio
information active on their dates. Event order is preserved. Depending on
multiple_matches, one event can produce more than one output row.
Details
Claim and event files often contain an event date and policy identifier but
not the rating factors used at that point in time. The function performs an
interval match between those events and the portfolio history. Supplying a
policy identifier through by prevents an event from matching active periods
belonging to another policy.
This is a temporal matching operation rather than a portfolio reduction. See
merge_date_ranges() for consolidating connected coverage periods and
split_periods_to_months() for expanding periods into monthly records.
Multiple matches can be valid when one event relates to several concurrently
active coverages. They can also reveal overlapping or duplicated policy
periods. Use multiple_matches = "all" when every active record is relevant;
use "first" or "last" only when the source system defines which record
should take precedence.
With unmatched = "drop", events outside every applicable coverage period
are omitted. With unmatched = "keep", they remain visible with missing
portfolio fields. Retaining unmatched events is generally preferable during
data-quality review because it makes gaps in the policy history explicit.
The interval join is performed internally with data.table::foverlaps() on
local copies. Neither input is modified by reference. The output follows the
original order of dates and is always returned as a regular data.frame.
Examples
portfolio <- data.frame(
policy_id = c("P001", "P001", "P002"),
coverage_start = as.Date(c("2024-01-01", "2025-01-01", "2025-01-01")),
coverage_end = as.Date(c("2024-12-31", "2025-12-31", "2025-12-31")),
sector = c("Retail", "Industry", "Services"),
insured_amount = c(500000, 750000, 300000),
earned_premium = c(900, 1250, 650)
)
claims <- data.frame(
claim_id = c("C001", "C002", "C003"),
policy_id = c("P001", "P001", "P002"),
claim_date = as.Date(c("2024-06-15", "2025-08-10", "2026-01-10")),
claim_amount = c(12000, 45000, 8000)
)
# Attach the policy characteristics that applied on each claim date.
active_rows_by_date(
portfolio,
claims,
period_start = "coverage_start",
period_end = "coverage_end",
date = "claim_date",
by = "policy_id"
)
#> policy_id coverage_start coverage_end sector insured_amount earned_premium
#> 1 P001 2024-01-01 2024-12-31 Retail 500000 900
#> 2 P001 2025-01-01 2025-12-31 Industry 750000 1250
#> claim_id claim_amount claim_date
#> 1 C001 12000 2024-06-15
#> 2 C002 45000 2025-08-10
# Keep claims outside the available policy history for data-quality review.
active_rows_by_date(
portfolio,
claims,
period_start = "coverage_start",
period_end = "coverage_end",
date = "claim_date",
by = "policy_id",
unmatched = "keep"
)
#> policy_id coverage_start coverage_end sector insured_amount earned_premium
#> 1 P001 2024-01-01 2024-12-31 Retail 500000 900
#> 2 P001 2025-01-01 2025-12-31 Industry 750000 1250
#> 3 P002 <NA> <NA> <NA> NA NA
#> claim_id claim_amount claim_date
#> 1 C001 12000 2024-06-15
#> 2 C002 45000 2025-08-10
#> 3 C003 8000 2026-01-10
