Skip to contents

A loss triangle with four axes, in chainladder-python's order: index (segment, such as a line of business) x column (measure, such as paid and incurred) x origin period x development age in months. Cells that are not observed are NA; a zero is an observation.

Usage

triangle(
  data,
  origin,
  development,
  columns,
  keys = NULL,
  origin_grain = "Y",
  development_grain = "Y",
  cumulative = TRUE,
  development_is_valuation = FALSE,
  ptr = NULL
)

Arguments

data

A data.frame with one row per (keys, origin, development).

origin

Name of the origin column: Date, POSIXct (any day in the origin period) or whole-number years.

development

Name of the development column: ages in months (12, 24, ...), or valuation dates when development_is_valuation = TRUE.

columns

Names of the value columns (numeric).

keys

Names of the key columns, such as c("lob", "state"), or NULL for a single segment labelled "Total". Key values are stored as character and may not be NA; key names must differ from each other and from columns.

origin_grain, development_grain

Length of an origin period and spacing of the development ages: "M" (month), "Q" (quarter), "S" (semester) or "Y" (year). The development grain must divide the origin grain.

cumulative

Whether the values are cumulative (otherwise incremental).

development_is_valuation

Whether development holds valuation dates (Date, POSIXct, or whole-number years meaning December of that year) instead of ages.

ptr

A Triangle pointer; used internally.

Value

A triangle object.

Details

Segments are named by key columns such as lob and state. A triangle without keys has one segment, labelled "Total".

triangle() builds one from a long table, one row per (keys, origin, development). Origins span every period from the earliest to the latest row and ages every development period from the youngest to the oldest. Rows with the same (keys, origin, development) are summed, and NA values are missing. Incremental input (cumulative = FALSE) follows chainladder-python: a missing row is a period without movement.

Read-only properties: x@shape (index, column, origin and development lengths), x@keys (the key names), x@index (a data.frame with one column per key and one row per segment; no columns without keys), x@columns, x@origins (period labels such as "1981", "2021Q3", "2021H2" or "2021-08"), x@development (ages in months), x@valuation (the last day of the latest valuation month), x@origin_grain, x@development_grain, x@is_cumulative and x@values (a 4-D array with dimnames, whose index names join the key values with " / "). as.data.frame() gives the long table back, with the key columns by name.

Examples

long <- data.frame(
  year = c(2020, 2020, 2020, 2021, 2021, 2022),
  age = c(12, 24, 36, 12, 24, 12),
  paid = c(100, 150, 165, 110, 170, 120)
)
tri <- triangle(long, origin = "year", development = "age", columns = "paid")
tri
#> Triangle: paid (cumulative, valuation 2022-12)
#>        12   24   36
#> 2020  100  150  165
#> 2021  110  170
#> 2022  120
tri@values[1, "paid", , ]
#>       development
#> origin  12  24  36
#>   2020 100 150 165
#>   2021 110 170  NA
#>   2022 120  NA  NA
tri@valuation
#> [1] "2022-12-31"

# Two lines of business as a key column.
by_lob <- data.frame(
  lob = c("auto", "auto", "home"),
  year = c(2020, 2020, 2020),
  age = c(12, 24, 12),
  paid = c(100, 150, 40)
)
tri <- triangle(by_lob, "year", "age", "paid", keys = "lob")
tri@keys
#> [1] "lob"
tri@index
#>    lob
#> 1 auto
#> 2 home
as.data.frame(tri)
#>    lob     origin development paid
#> 1 auto 2020-01-01          12  100
#> 2 auto 2020-01-01          24  150
#> 3 home 2020-01-01          12   40