| Title: | Actuarial Helpers for Triangles, Exposures and Czech Birth Numbers |
|---|---|
| Description: | A collection of utilities that grew out of day-to-day non-life actuarial work at Com-PASS Advisory. Provides helpers for building chain-ladder triangles (cumulative, decumulative, run-off, development factors with optional weighting), constructing exposure columns from policy start/end dates, parsing Czech birth numbers ('rodné číslo') into dates, generating smooth RGB color palettes for charts, and loading multi-sheet 'xlsx'/'xlsb' files into a list of data frames. The chain-ladder helpers follow the standard methodology of Mack (1993) <doi:10.2143/AST.23.2.2005092>. |
| Authors: | Ondřej Vít [aut, cre] |
| Maintainer: | Ondřej Vít <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.1 |
| Built: | 2026-05-12 23:05:46 UTC |
| Source: | https://github.com/cran/vitopack |
source columnThin wrapper around data.table::rbindlist() that prepends a column called
source with the names of lst. Returns NULL for an empty input.
bind_with_source(lst)bind_with_source(lst)
lst |
A named list of data frames to bind together. |
A data.table with all columns from the inputs and an added
source column, or NULL if lst is empty.
bind_with_source(list( a = data.frame(x = 1:2, y = 3:4), b = data.frame(x = 5, z = 9) ))bind_with_source(list( a = data.frame(x = 1:2, y = 3:4), b = data.frame(x = 5, z = 9) ))
Combines period consecutive sub-period diagonals/columns of a
cumulative triangle into one annual diagonal/column. Useful when the
source data is monthly or quarterly and the report wants annual figures.
create_annual_triangle(cum_trg, period = 4)create_annual_triangle(cum_trg, period = 4)
cum_trg |
A cumulative numeric triangle. |
period |
Integer - number of sub-periods that make up one year
(default |
A cumulative annual triangle (numeric matrix).
# 4x4 quarterly cumulative triangle (only the lower-left corner is real data) q_trg <- matrix(NA_real_, 4, 4) q_trg[1, ] <- c(1, 2, 3, 4) q_trg[2, 1:3] <- c(2, 4, 5) q_trg[3, 1:2] <- c(3, 5) q_trg[4, 1] <- 4 create_annual_triangle(q_trg, period = 4)# 4x4 quarterly cumulative triangle (only the lower-left corner is real data) q_trg <- matrix(NA_real_, 4, 4) q_trg[1, ] <- c(1, 2, 3, 4) q_trg[2, 1:3] <- c(2, 4, 5) q_trg[3, 1:2] <- c(3, 5) q_trg[4, 1] <- 4 create_annual_triangle(q_trg, period = 4)
Averages the per-cell development factors of a CHL factor triangle along diagonals. For each requested window length, returns one row with the simple-average factor per development period.
create_avg_coefs(chl_trg, avg_length = "full")create_avg_coefs(chl_trg, avg_length = "full")
chl_trg |
A development-factor triangle (e.g. the output of
|
avg_length |
Vector – each element either |
A data.frame with one row per avg_length element.
For every cell (i, j) of a cumulative triangle returns
cum_trg[i, j] / cum_trg[i, j-1]. The first column and the upper-right
NA corner are left as NA.
create_chl_coef_triangle(cum_trg)create_chl_coef_triangle(cum_trg)
cum_trg |
A cumulative numeric triangle. |
A numeric matrix of the same shape with development factors.
cum <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_chl_coef_triangle(cum)cum <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_chl_coef_triangle(cum)
Computes one row of development factors per requested length ("full" or
an integer giving how many of the most recent rows to use). Factors are
aggregated using the standard volume-weighted formula
sum(cum[, j]) / sum(cum[, j - 1]).
create_chl_coefs(cum_trg, chl_length = "full")create_chl_coefs(cum_trg, chl_length = "full")
cum_trg |
A cumulative numeric triangle. |
chl_length |
A vector – each element is either the literal |
A data.frame with one row per chl_length element, the first
column labelling the row and the remaining columns holding the
development factors.
cum <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_chl_coefs(cum, chl_length = c("full", 2))cum <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_chl_coefs(cum, chl_length = c("full", 2))
Same idea as create_chl_coefs() but every cell is weighted by an
arbitrary trg_weight matrix evaluated at the previous column
(j - 1). Useful when the natural exposure differs from the cumulative
triangle itself (e.g. paid claims weighted by exposure-as-of-prior-period).
create_chl_coefs_weighted(cum_trg, trg_weight, chl_length = "full")create_chl_coefs_weighted(cum_trg, trg_weight, chl_length = "full")
cum_trg |
Cumulative triangle. |
trg_weight |
Weight matrix of the same shape as |
chl_length |
As in |
A data.frame analogous to the output of create_chl_coefs().
Variant of create_chl_coefs_weighted() that uses trg_weight[, j]
instead of trg_weight[, j - 1], i.e. the weight evaluated at the
developed (forward-looking) column.
create_chl_coefs_weighted_future(cum_trg, trg_weight, chl_length = "full")create_chl_coefs_weighted_future(cum_trg, trg_weight, chl_length = "full")
cum_trg |
Cumulative triangle. |
trg_weight |
Weight matrix of the same shape as |
chl_length |
As in |
A data.frame analogous to the output of create_chl_coefs().
Creates an interactive plotly line+marker chart of the selected columns
of data_matrix, with the row names used as the time axis.
create_chl_trg_visualization(data_matrix, columns)create_chl_trg_visualization(data_matrix, columns)
data_matrix |
A named matrix where row names act as the x-axis. |
columns |
Character or numeric vector – which columns to plot. |
A plotly htmlwidget.
## Not run: trg <- matrix(c(1, 1.2, 1.05, 1, 1.3, NA, 1, NA, NA), 3, dimnames = list(c("2022", "2023", "2024"), c("0", "1", "2"))) create_chl_trg_visualization(trg, columns = c("1", "2")) ## End(Not run)## Not run: trg <- matrix(c(1, 1.2, 1.05, 1, 1.3, NA, 1, NA, NA), 3, dimnames = list(c("2022", "2023", "2024"), c("0", "1", "2"))) create_chl_trg_visualization(trg, columns = c("1", "2")) ## End(Not run)
Like create_chl_trg_visualization(), but the x-axis is left as the raw
character row names (no coercion to numeric).
create_chl_trg_visualization_pvzp(data_matrix, columns)create_chl_trg_visualization_pvzp(data_matrix, columns)
data_matrix |
A named matrix where row names act as the x-axis. |
columns |
Character or numeric vector – which columns to plot. |
A plotly htmlwidget.
Turns an incremental triangle into a cumulative one by running cumulative sums along the rows (development direction).
create_cumulative_triangle(trg)create_cumulative_triangle(trg)
trg |
An incremental triangle (numeric matrix) where the upper-right
|
A numeric matrix of the same shape, cumulatively summed.
trg <- matrix(c(10, 5, 2, 20, 7, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_cumulative_triangle(trg)trg <- matrix(c(10, 5, 2, 20, 7, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_cumulative_triangle(trg)
Inverse of create_cumulative_triangle().
create_decumulative_triangle(trg)create_decumulative_triangle(trg)
trg |
A cumulative triangle. |
The incremental triangle.
cum_trg <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_decumulative_triangle(cum_trg)cum_trg <- matrix(c(10, 30, 32, 20, 27, NA, 15, NA, NA), nrow = 3, byrow = TRUE) create_decumulative_triangle(cum_trg)
For each pair (condition_names[i], new_cols_names[i]) the function adds a
new column to data initialised to 0. Where the row matches
data[[condition_var]] == condition_names[i], the new column is set to the
value of data[[values_var]] (evaluated as an expression - see Details).
create_find_columns( data, condition_names, new_cols_names, condition_var, values_var )create_find_columns( data, condition_names, new_cols_names, condition_var, values_var )
data |
A data.frame or data.table. |
condition_names |
Character vector of values to match against
|
new_cols_names |
Character vector with the names of the new columns to
create. Same length as |
condition_var |
Character scalar - name of the column to test. |
values_var |
Character scalar - expression that yields the value to assign where the condition matches. |
The values_var argument is parsed and evaluated inside data[, ...],
which means it can be a bare column name or a small data.table-style
expression. The function modifies data by reference (via
data.table::setDT()) and also returns it invisibly to allow chaining.
The updated data.table (modified in place).
dt <- data.frame(line = c("MTPL", "CASCO", "MTPL"), premium = c(100, 200, 300)) create_find_columns( data = dt, condition_names = c("MTPL", "CASCO"), new_cols_names = c("MTPL_premium", "CASCO_premium"), condition_var = "line", values_var = "premium" )dt <- data.frame(line = c("MTPL", "CASCO", "MTPL"), premium = c(100, 200, 300)) create_find_columns( data = dt, condition_names = c("MTPL", "CASCO"), new_cols_names = c("MTPL_premium", "CASCO_premium"), condition_var = "line", values_var = "premium" )
For each multiple_exp_names[i] the function creates a new column
new_variable_names[i] equal to multiple_exp_names[i] * multiply_var.
create_multiple_columns_m( data, new_variable_names, multiple_exp_names, multiply_var )create_multiple_columns_m( data, new_variable_names, multiple_exp_names, multiply_var )
data |
A data frame. |
new_variable_names |
Character vector - names of the resulting columns. |
multiple_exp_names |
Character vector - names of the columns to multiply. |
multiply_var |
Character scalar - name of the multiplier column. |
A data frame with the new multiplied columns added.
df <- data.frame(exp_q1 = c(0.25, 0.5), exp_q2 = c(0.5, 0.5), premium = c(100, 200)) create_multiple_columns_m( data = df, new_variable_names = c("prem_q1", "prem_q2"), multiple_exp_names = c("exp_q1", "exp_q2"), multiply_var = "premium" )df <- data.frame(exp_q1 = c(0.25, 0.5), exp_q2 = c(0.5, 0.5), premium = c(100, 200)) create_multiple_columns_m( data = df, new_variable_names = c("prem_q1", "prem_q2"), multiple_exp_names = c("exp_q1", "exp_q2"), multiply_var = "premium" )
For each requested exposure period [start_months[i], end_months[i]]
the function adds a column exp_names[i] to data containing the
overlap of that period with each row's policy span
[start_policy_var, end_policy_var], expressed in years
(days / 365).
create_policy_exposure_columns_m( data, exp_names, start_months, end_months, start_policy_var, end_policy_var )create_policy_exposure_columns_m( data, exp_names, start_months, end_months, start_policy_var, end_policy_var )
data |
A data.frame or data.table. |
exp_names |
Character vector with the names of the new exposure columns. |
start_months, end_months
|
Character vectors of period boundaries that
can be coerced via |
start_policy_var, end_policy_var
|
Names of the columns holding the policy start and end dates. |
The updated data.table (modified in place).
dt <- data.frame( policy_start = as.Date(c("2024-01-15", "2024-06-01")), policy_end = as.Date(c("2024-12-31", "2025-05-31")) ) create_policy_exposure_columns_m( data = dt, exp_names = c("exp_2024_Q1", "exp_2024_Q2"), start_months = c("2024-01-01", "2024-04-01"), end_months = c("2024-03-31", "2024-06-30"), start_policy_var = "policy_start", end_policy_var = "policy_end" )dt <- data.frame( policy_start = as.Date(c("2024-01-15", "2024-06-01")), policy_end = as.Date(c("2024-12-31", "2025-05-31")) ) create_policy_exposure_columns_m( data = dt, exp_names = c("exp_2024_Q1", "exp_2024_Q2"), start_months = c("2024-01-01", "2024-04-01"), end_months = c("2024-03-31", "2024-06-30"), start_policy_var = "policy_start", end_policy_var = "policy_end" )
Sister of create_policy_exposure_columns_m() - same logic, but the
exposure is expressed in days (rounded) instead of years.
create_policy_exposure_days_columns( data, exp_names, start_months, end_months, start_policy_var, end_policy_var )create_policy_exposure_days_columns( data, exp_names, start_months, end_months, start_policy_var, end_policy_var )
data |
A data.frame or data.table. |
exp_names |
Character vector with the names of the new exposure columns. |
start_months, end_months
|
Character vectors of period boundaries that
can be coerced via |
start_policy_var, end_policy_var
|
Names of the columns holding the policy start and end dates. |
The updated data.table (modified in place).
dt <- data.frame( policy_start = as.Date("2024-01-15"), policy_end = as.Date("2024-12-31") ) create_policy_exposure_days_columns( data = dt, exp_names = "exp_days_q1", start_months = "2024-01-01", end_months = "2024-03-31", start_policy_var = "policy_start", end_policy_var = "policy_end" )dt <- data.frame( policy_start = as.Date("2024-01-15"), policy_end = as.Date("2024-12-31") ) create_policy_exposure_days_columns( data = dt, exp_names = "exp_days_q1", start_months = "2024-01-01", end_months = "2024-03-31", start_policy_var = "policy_start", end_policy_var = "policy_end" )
Given a one-row data frame of development factors as returned by
create_chl_coefs(), computes the cumulative product from each
development period to the tail.
create_product_coefs(chl_coefs, name = "Product")create_product_coefs(chl_coefs, name = "Product")
chl_coefs |
A one-row data frame whose first column is a label and
whose other columns hold development factors. (As returned by
|
name |
Character – label for the resulting row. |
A character vector of cumulative-product factors with name as
the first element.
Compares each diagonal's lower-tail cumulative ultimate against the main diagonal's. Returns the run-off differences in chronological order.
create_run_off_check(cum_trg)create_run_off_check(cum_trg)
cum_trg |
A cumulative numeric triangle. |
Numeric vector of run-off differences with length = nrow(cum_trg) - 1.
Aggregates value over (row_num, col_num) (optionally after filtering
by one or more cond_variable == cond_value pairs) and arranges the
result into a square rows x rows matrix where the upper-right corner
beyond the main anti-diagonal is NA.
create_triangle( data, row_num, col_num, value, cond_variable = NULL, cond_value = NULL, rows = NULL )create_triangle( data, row_num, col_num, value, cond_variable = NULL, cond_value = NULL, rows = NULL )
data |
A data frame (or tibble) with at least the columns named by
|
row_num |
Character - name of the column with row indices (origin periods, 1-based). |
col_num |
Character - name of the column with column indices (development periods, 0-based). |
value |
Character - name of the numeric column to be summed. |
cond_variable |
Optional character vector - names of columns to filter on. |
cond_value |
Optional vector of values, same length as
|
rows |
Optional integer - size of the output triangle. Defaults to
the maximum value of |
A numeric rows x rows matrix.
df <- expand.grid(origin = 1:3, dev = 0:2) df$paid <- c(100, 50, 20, 120, 40, NA, 130, NA, NA) df <- df[!is.na(df$paid), ] create_triangle(df, row_num = "origin", col_num = "dev", value = "paid")df <- expand.grid(origin = 1:3, dev = 0:2) df$paid <- c(100, 50, 20, 120, 40, NA, 130, NA, NA) df <- df[!is.na(df$paid), ] create_triangle(df, row_num = "origin", col_num = "dev", value = "paid")
Returns the values along the diag_num-th anti-diagonal of trg,
starting from the bottom-left.
diag_reader(trg, diag_num = nrow(trg))diag_reader(trg, diag_num = nrow(trg))
trg |
A square numeric matrix (a triangle). |
diag_num |
Integer - which anti-diagonal to read. Defaults to the main (last) one. |
A numeric vector with the values on that diagonal.
trg <- matrix(1:9, nrow = 3) diag_reader(trg) diag_reader(trg, diag_num = 2)trg <- matrix(1:9, nrow = 3) diag_reader(trg) diag_reader(trg, diag_num = 2)
For each anti-diagonal k = 1..nrow(trg) returns the sum of its values.
diag_sums(trg)diag_sums(trg)
trg |
A square numeric matrix (a triangle). |
Numeric vector of length nrow(trg).
diag_sums(matrix(c(10, 5, 2, 20, 7, NA, 15, NA, NA), nrow = 3, byrow = TRUE))diag_sums(matrix(c(10, 5, 2, 20, 7, NA, 15, NA, NA), nrow = 3, byrow = TRUE))
Used in rolling re-runs: pads old_trg with one extra row and column of
NA, then fills in the gaps from new_trg (which already contains the
newly observed diagonal).
diag_writer(old_trg, new_trg)diag_writer(old_trg, new_trg)
old_trg |
A |
new_trg |
A |
The merged (n+1) x (n+1) matrix.
old <- matrix(c(10, 5, 20, NA), nrow = 2, byrow = TRUE) new <- matrix(c(10, 5, 3, 20, 6, NA, 25, NA, NA), nrow = 3, byrow = TRUE) diag_writer(old, new)old <- matrix(c(10, 5, 20, NA), nrow = 2, byrow = TRUE) new <- matrix(c(10, 5, 3, 20, 6, NA, 25, NA, NA), nrow = 3, byrow = TRUE) diag_writer(old, new)
n evenly spaced colors from a rainbow data frameThree flavours are exported. They differ only in the post-processing they
apply after picking equally-spaced rows from rgb_df:
get_colors(rgb_df, n_colors) get_colors_plus(rgb_df, n_colors) get_colors_duo(rgb_df, n_colors)get_colors(rgb_df, n_colors) get_colors_plus(rgb_df, n_colors) get_colors_duo(rgb_df, n_colors)
rgb_df |
A data frame with columns |
n_colors |
Integer >= 2 – number of colors to return. |
get_colors() – no post-processing.
get_colors_plus() – every other color is darkened (x0.75) or
lightened (towards 255 with weight 0.7), creating a strong duo pattern.
get_colors_duo() – every other color is darkened (x0.8) or lightened
(weight 0.6), milder than the _plus variant.
A character vector of length n_colors with hex color codes
("#RRGGBB").
rgb_df <- rgb_colors_for_plot() get_colors(rgb_df, 5) get_colors_plus(rgb_df, 6) get_colors_duo(rgb_df, 6)rgb_df <- rgb_colors_for_plot() get_colors(rgb_df, 5) get_colors_plus(rgb_df, 6) get_colors_duo(rgb_df, 6)
.xlsx workbook into a named listWrapper around readxl::excel_sheets() and readxl::read_xlsx(). Returns
a list whose names are the sheet names and whose elements are the parsed
tibbles.
load_excel_sheets(path, range = NULL)load_excel_sheets(path, range = NULL)
path |
Path to the workbook. |
range |
Optional cell range passed to |
A named list of data frames – one entry per sheet.
## Not run: sheets <- load_excel_sheets("path/to/file.xlsx") sheets <- load_excel_sheets("path/to/file.xlsx", range = "A1:F100") ## End(Not run)## Not run: sheets <- load_excel_sheets("path/to/file.xlsx") sheets <- load_excel_sheets("path/to/file.xlsx", range = "A1:F100") ## End(Not run)
.xlsb workbook into a named listWrapper around the readxlsb package. Returns a list whose names are the
sheet names and whose elements are the parsed data frames.
load_xlsb_sheets(path, range = NULL)load_xlsb_sheets(path, range = NULL)
path |
Path to the workbook. |
range |
Optional cell range passed to |
A named list of data frames – one entry per sheet.
readxlsb was archived from CRAN in 2024-09-25. To use this
function you have to install it from GitHub manually:
remotes::install_github("velofrog/readxlsb").
## Not run: # Requires: remotes::install_github("velofrog/readxlsb") sheets <- load_xlsb_sheets("path/to/file.xlsb") ## End(Not run)## Not run: # Requires: remotes::install_github("velofrog/readxlsb") sheets <- load_xlsb_sheets("path/to/file.xlsb") ## End(Not run)
Convenience wrapper around base::format() with sensible Czech-friendly
defaults (thin space as group separator, . as decimal mark, no
scientific notation).
numeric_format(number)numeric_format(number)
number |
Numeric vector. |
A character vector of formatted numbers.
numeric_format(c(1234567, 89.5))numeric_format(c(1234567, 89.5))
Convenience wrapper that calls rgb_colors_for_plot() and
get_colors_duo() and renders the result as a stacked bar chart.
plot_color_bars(n_colors)plot_color_bars(n_colors)
n_colors |
Integer >= 2 – number of palette stops to plot. |
Invisible NULL. Called for the side effect of plotting.
plot_color_bars(12)plot_color_bars(12)
Prints print_text to the console wrapped in an ANSI color code chosen by
color_num. The color index cycles modulo 8 so any positive integer is
valid.
rainbow_cat(print_text, color_num)rainbow_cat(print_text, color_num)
print_text |
Character – the text to print. |
color_num |
Integer – color index (cycled modulo 8). |
Invisible NULL. Called for the side effect of printing.
rainbow_cat("Hello in green", 3)rainbow_cat("Hello in green", 3)
These three variants implement slightly different rules for resolving the century (the two-digit year stored in a Czech rodne cislo). They are kept as separate functions so existing code that depends on a particular rule keeps working.
rc_to_birth_day(rc_s_lomitkem) rc_to_birth_day_2(rc_s_lomitkem) rc_to_birth_day_3(rc_s_lomitkem)rc_to_birth_day(rc_s_lomitkem) rc_to_birth_day_2(rc_s_lomitkem) rc_to_birth_day_3(rc_s_lomitkem)
rc_s_lomitkem |
Character vector. Czech birth number, optionally with
a |
rc_to_birth_day() - assumes the input has the trailing 4-digit suffix
separated by a slash ("YYMMDD/XXXX", total length 11). Years < 54 go
into the 21st century, otherwise the 20th.
rc_to_birth_day_2() - does not check length and uses cut-off 25 -
anything < 25 is 21st century, otherwise 20th.
rc_to_birth_day_3() - like rc_to_birth_day() but with cut-off 25.
All three apply the women-offset (+50 added to the month for women, so months 51-62 -> 01-12).
A Date vector of the same length as rc_s_lomitkem.
rc_to_birth_day("905615/1234") # man, 1990-06-15 rc_to_birth_day("9056151234") # man, 1990-06-15 (no slash, length 10) rc_to_birth_day_2("055615/1234") # cut-off 25 -> 2005-06-15 rc_to_birth_day_3("055615/1234") # 11 chars + cut-off 25 -> 2005-06-15rc_to_birth_day("905615/1234") # man, 1990-06-15 rc_to_birth_day("9056151234") # man, 1990-06-15 (no slash, length 10) rc_to_birth_day_2("055615/1234") # cut-off 25 -> 2005-06-15 rc_to_birth_day_3("055615/1234") # 11 chars + cut-off 25 -> 2005-06-15
Produces a tibble of r, g, b channel values walking through the six
canonical rainbow segments (red -> yellow -> green -> cyan -> blue -> purple
-> red). The argument selects which segments to include and in which order.
rgb_colors_for_plot(colors_changes_vector = c(3:6, 1))rgb_colors_for_plot(colors_changes_vector = c(3:6, 1))
colors_changes_vector |
Integer vector with values in |
A tibble::tibble() with columns r, g, b.
head(rgb_colors_for_plot())head(rgb_colors_for_plot())
Replaces the column names with 0..ncol-1 (development periods) and sets
the row names to claim_period_names[1:nrow(trg)] (origin periods).
triangle_namer(trg, claim_period_names)triangle_namer(trg, claim_period_names)
trg |
A square numeric matrix. |
claim_period_names |
Character vector of origin-period labels (must
be at least |
The same matrix with dimnames set.
trg <- matrix(1:9, 3, 3) triangle_namer(trg, c("2022", "2023", "2024"))trg <- matrix(1:9, 3, 3) triangle_namer(trg, c("2022", "2023", "2024"))