Triangle#

class chainladder.Triangle(data: DataFrame | DataFrameXchg | dict | None = None, origin: str | list | None = None, development: str | list | None = None, columns: str | list | None = None, index: str | list | None = None, origin_format: str | None = None, development_format: str | None = None, cumulative: bool | None = None, array_backend: str = None, pattern=False, trailing: bool = True, *args, **kwargs)[source]#

The core data structure of the chainladder package

Parameters:
data: DataFrame | DataFrameXchg | dict

A single dataframe that contains columns representing all other arguments to the Triangle constructor. One may supply a DataFrame-like object (referred to as DataFrameXchg) supporting the __dataframe__ protocol, which will then be converted to a pandas DataFrame. If supplying a dict, it must be structured such that a pandas DataFrame created from it will be accepted by the constructor. If omitted (or if all arguments are omitted), an empty Triangle is returned.

origin: str

Name of the column in data representing the accident, reporting, or more generally the origin period. Maps to the Origin dimension.

development: str

Name of the column in data representing the development or valuation period. Maps to the Development dimension. If omitted, the Triangle is treated as having a single development period (e.g. a latest-diagonal-only view).

columns: str or list

Name(s) of the column(s) in data holding the numeric values that will map to the columns dimension. If omitted, a single 'Total' key is generated.

index: str or list

Name(s) of the column(s) in data that will map to the index dimension. If omitted, a single 'Total' key is generated.

origin_format: str

A string representation of the date format of the origin column (e.g. '%Y-%m-%d'). If omitted, the date format is inferred by pandas.

development_format: str

A string representation of the date format of the development column. If omitted, the date format is inferred by pandas.

cumulative: bool

Whether the triangle is cumulative or incremental. This attribute is required to use the grain and dev_to_val methods and will be automatically set when invoking cum_to_incr or incr_to_cum methods.

trailing: bool, default True

Controls how the period-end month is inferred from origin and development dates. When False, December is treated as the period end (i.e., calendar fiscal periods). When True, the period end is inferred from the data itself. This is useful when origin dates do not align with calendar period boundaries.

array_backend: str, optional (default = None)

Backend used to store the underlying values array. One of 'numpy', 'sparse', or 'cupy' (if installed). If None, falls back to cl.options.ARRAY_BACKEND.

Attributes:
index: Series

Represents all available levels of the index dimension.

columns: Series

Represents all available levels of the value dimension.

origin: DatetimeIndex

Represents all available levels of the origin dimension.

development: Series

Represents all available levels of the development dimension.

key_labels: list

Represents the index axis labels

virtual_columns: Series

Represents the subset of columns of the triangle that are virtual.

valuation: DatetimeIndex

Represents all valuation dates of each cell in the Triangle.

origin_grain: str

The grain of the origin vector (‘Y’, ‘S’, ‘Q’, ‘M’)

development_grain: str

The grain of the development vector (‘Y’, ‘S’, ‘Q’, ‘M’)

shape: tuple

The 4D shape of the triangle instance with axes corresponding to (index, columns, origin, development)

link_ratio, age_to_age

Displays age-to-age ratios for the triangle.

valuation_datedate

The latest valuation date of the data

loc: Triangle

pandas-style loc accessor

iloc: Triangle

pandas-style iloc accessor

latest_diagonal: Triangle

The latest diagonal of the triangle

is_cumulative: bool

Whether the triangle is cumulative or not

is_ultimate: bool

Whether the triangle has an ultimate valuation

is_full: bool

Whether lower half of Triangle has been filled in

is_val_tri:

Whether the triangle development period is expressed as valuation periods.

values: array

4D numpy array underlying the Triangle instance

T: Triangle

Transpose index and columns of object. Only available when Triangle is convertible to DataFrame.

Examples

Constructing a Triangle from a Pandas DataFrame.

import pandas as pd
df = pd.DataFrame(
    data={
        'origin': [1981, 1981, 1981, 1981, 1982, 1982, 1982, 1983, 1983, 1984],
        'development': [1981, 1982, 1983, 1984, 1982, 1983, 1984, 1983, 1984, 1984],
        'reported': [5012, 8269, 10907, 11805, 106, 4285, 5396, 3410, 8992, 5655],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=True,
)
print(tr)
          12      24       36       48
1981  5012.0  8269.0  10907.0  11805.0
1982   106.0  4285.0   5396.0      NaN
1983  3410.0  8992.0      NaN      NaN
1984  5655.0     NaN      NaN      NaN

When another dimension is added, such as an additional column, the Triangle becomes multidimensional. In this case, printing displays the Triangle’s metadata rather than its contents.

df = pd.DataFrame(
    data={
        'origin': [1981, 1981, 1981, 1981, 1982, 1982, 1982, 1983, 1983, 1984],
        'development': [1981, 1982, 1983, 1984, 1982, 1983, 1984, 1983, 1984, 1984],
        'reported': [5012, 8269, 10907, 11805, 106, 4285, 5396, 3410, 8992, 5655],
        'paid': [2506, 4135, 5454, 5903, 53, 2143, 2698, 1705, 4496, 2828],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported', 'paid'],
    cumulative=True,
)
print(tr)
            Triangle Summary
Valuation:           1984-12
Grain:                  OYDY
Shape:          (1, 2, 4, 4)
Index:               [Total]
Columns:    [reported, paid]

Using the index parameter creates a multi-dimensional Triangle split by a categorical grouping, for example Line of Business.

df = pd.DataFrame(
    data={
         'lob': ['auto', 'auto', 'auto', 'home', 'home', 'home'],
        'origin': [2020, 2020, 2021, 2020, 2020, 2021],
        'development': [2020, 2021, 2021, 2020, 2021, 2021],
        'reported': [100, 150, 80, 200, 280, 160],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    index=['lob'],
    cumulative=True,
)
print(tr)
           Triangle Summary
Valuation:          2021-12
Grain:                 OYDY
Shape:         (2, 1, 2, 2)
Index:                [lob]
Columns:         [reported]

Non-standard date strings can be parsed by specifying origin_format and development_format using Python strftime codes.

df = pd.DataFrame(
    data={
        'origin': ['2020-01', '2020-01', '2020-02', '2020-02'],
        'development': ['2020-01', '2020-02', '2020-02', '2020-03'],
        'reported': [100, 150, 200, 280],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    origin_format='%Y-%m',
    development='development',
    development_format='%Y-%m',
    columns=['reported'],
    cumulative=True,
)
print(tr)
             1      2   3
2020-01  100.0  150.0 NaN
2020-02  200.0  280.0 NaN
2020-03    NaN    NaN NaN

Setting cumulative=False builds an incremental Triangle, where each cell is the amount accrued within that development period rather than the cumulative total to date.

df = pd.DataFrame(
    data={
        'origin': [1981, 1981, 1981, 1981, 1982, 1982, 1982, 1983, 1983, 1984],
        'development': [1981, 1982, 1983, 1984, 1982, 1983, 1984, 1983, 1984, 1984],
        'reported': [5012, 3257, 2638, 898, 106, 4179, 1111, 3410, 5582, 5655],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=False,
)
print(tr)
          12      24      36     48
1981  5012.0  3257.0  2638.0  898.0
1982   106.0  4179.0  1111.0    NaN
1983  3410.0  5582.0     NaN    NaN
1984  5655.0     NaN     NaN    NaN

By default (trailing=False), chainladder uses December as the fiscal period end, so origin dates are assigned to calendar quarters. Setting trailing=True instead infers the period end from the data itself, producing quarters aligned to the origin dates.

df = pd.DataFrame(
    data={
        'origin': ['2023-05', '2023-08', '2023-11', '2024-02'],
        'development': ['2024-04', '2024-04', '2024-04', '2024-04'],
        'premium': [100, 130, 160, 140],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    origin_format='%Y-%m',
    development='development',
    development_format='%Y-%m',
    columns=['premium'],
    cumulative=True,
    trailing=False,
)
print(tr)
        2024-04
2023Q2    100.0
2023Q3    130.0
2023Q4    160.0
2024Q1    140.0
2024Q2      NaN
tr = cl.Triangle(
    data=df,
    origin='origin',
    origin_format='%Y-%m',
    development='development',
    development_format='%Y-%m',
    columns=['premium'],
    cumulative=True,
    trailing=True,
)
print(tr)
        2024Q2
2024Q1   100.0
2024Q2   130.0
2024Q3   160.0
2024Q4   140.0
align_pattern(X: Triangle, sample_weight: Triangle | None = None) Triangle[source]#

Vertically align a selected pattern to origin period latest diagonal. Triangle must be a selected pattern.

Parameters:
X: Triangle
The target triangle to align to
sample_weight: Triangle, option (default=None)
Exposure triangle
Returns:
Triangle

Triangle of selected pattern across origin periods

append(other)[source]#

Append rows of other to the end of caller, returning a new object.

Parameters:
otherTriangle

The data to append.

Returns:
New Triangle with appended data.
astype(dtype, inplace=True)[source]#

Copy of the array, cast to a specified type.

Parameters:
dtypestr or dtype

Typecode or data-type to which the array is cast.

copybool, optional

By default, astype always returns a newly allocated array.

Returns:
Triangle as new datatype
compute(*args, **kwargs)[source]#

Materialize a lazy dask-backed Triangle.

When values is a dask array, compute it and update array_backend to match the resulting array type. Returns self unchanged when the Triangle is already materialized.

Returns:
Triangle
copy()[source]#

Return a shallow copy of the Triangle.

Returns:
Triangle

A new Triangle with copied values and shared metadata.

cum_to_incr(inplace=False)[source]#

Method to convert an cumlative triangle into a incremental triangle.

Parameters:
inplace: bool

Set to True will update the instance data attribute inplace

Returns:
Updated instance of triangle accumulated along the origin

Examples

cl.load_sample('ukmotor') is a cumulative Triangle. cum_to_incr differences each cell against the prior development period, returning per-period increments.

tr = cl.load_sample('ukmotor')
print(tr.cum_to_incr())
          12      24      36      48      60     72     84
2007  3511.0  3215.0  2266.0  1712.0  1059.0  587.0  340.0
2008  4001.0  3702.0  2278.0  1180.0   956.0  629.0    NaN
2009  4355.0  3932.0  1946.0  1522.0  1238.0    NaN    NaN
2010  4295.0  3455.0  2023.0  1320.0     NaN    NaN    NaN
2011  4150.0  3747.0  2320.0     NaN     NaN    NaN    NaN
2012  5102.0  4548.0     NaN     NaN     NaN    NaN    NaN
2013  6283.0     NaN     NaN     NaN     NaN    NaN    NaN
cumsum(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for cumsum functionality.

describe(*args, **kwargs)[source]#

Refer to pandas for describe functionality.

dev_to_val(inplace=False)[source]#

Converts triangle from a development lag triangle to a valuation triangle.

Parameters:
inplacebool

Whether to mutate the existing Triangle instance or return a new one.

Returns:
Triangle

Updated instance of the triangle with valuation periods.

Examples

cl.load_sample('ukmotor') is a 7x7 cumulative Triangle in development form. Each column represents months of development from the origin year.

tr = cl.load_sample('ukmotor')
print(tr)
          12      24       36       48       60       72       84
2007  3511.0  6726.0   8992.0  10704.0  11763.0  12350.0  12690.0
2008  4001.0  7703.0   9981.0  11161.0  12117.0  12746.0      NaN
2009  4355.0  8287.0  10233.0  11755.0  12993.0      NaN      NaN
2010  4295.0  7750.0   9773.0  11093.0      NaN      NaN      NaN
2011  4150.0  7897.0  10217.0      NaN      NaN      NaN      NaN
2012  5102.0  9650.0      NaN      NaN      NaN      NaN      NaN
2013  6283.0     NaN      NaN      NaN      NaN      NaN      NaN

Calling dev_to_val reshapes the columns from development lags to valuation periods, so each column corresponds to a calendar year.

print(tr.dev_to_val())
        2007    2008    2009     2010     2011     2012     2013
2007  3511.0  6726.0  8992.0  10704.0  11763.0  12350.0  12690.0
2008     NaN  4001.0  7703.0   9981.0  11161.0  12117.0  12746.0
2009     NaN     NaN  4355.0   8287.0  10233.0  11755.0  12993.0
2010     NaN     NaN     NaN   4295.0   7750.0   9773.0  11093.0
2011     NaN     NaN     NaN      NaN   4150.0   7897.0  10217.0
2012     NaN     NaN     NaN      NaN      NaN   5102.0   9650.0
2013     NaN     NaN     NaN      NaN      NaN      NaN   6283.0
development_correlation(p_critical=0.5)[source]#

Mack (1997) test for correlations between subsequent development factors. Results should be within confidence interval range otherwise too much correlation

Parameters:
p_critical: float (default=0.10)

Value between 0 and 1 representing the confidence level for the test. A value of 0.1 implies 90% confidence.

Returns
——-

DevelopmentCorrelation object with t, t_critical, t_expectation, t_variance, and range attributes.

Examples

tr = cl.load_sample('raa')
dc = tr.development_correlation()
print(bool(dc.t_critical.iloc[0, 0]))
False

t_critical reports whether the calculated rank correlation falls outside the no-correlation confidence interval. False indicates the development factors are not significantly correlated.

diff(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for diff functionality.

drop(labels=None, axis=1)[source]#

Drop specified labels from rows or columns.

Remove rows or columns by specifying label names and corresponding axis, or by specifying directly index or column names.

Parameters:
label: single label or list-like

Index or column labels to drop.

axis: {0 or ‘index’, 1 or ‘columns’}, default 1

Whether to drop labels from the index (0 or ‘index’) or columns (1 or ‘columns’).

Returns:
Triangle
drop_duplicates(*args, **kwargs)[source]#

Refer to pandas for drop_duplicates functionality.

dropna()[source]#

Method that removes origin/development vectors from edge of a triangle that are all missing values. This may come in handy for a new line of business that doesn’t have origins/developments of an existing line in the same triangle.

exp()[source]#

Return the exponential of each element.

Returns:
Triangle
fillna(value=None, inplace=False)[source]#

Fill nan with ‘value’ by axis.

Parameters:
value: single value or array-like values, default = None

Value(s) to fill across the axis.

inplace: boolean, default = False

Whether to modify the triangle object directly (True), or return a new modified triangle (False).

Returns:
Triangle
fillzero(inplace=False)[source]#

Fill nan with 0 by axis. separate function from fillna() because fillna(0) isn’t working

Parameters:
inplace: boolean, default = False

Whether to modify the triangle object directly (True), or return a new modified triangle (False).

Returns:
Triangle
get_array_module(arr: ArrayLike = None) ModuleType[source]#

Returns the module pertaining to the backend underlying the supplied array. If no array is supplied, this method will return the array_backend of the TriangleBase.

Parameters:
arr: ArrayLike

An array-like object. For example, the values used in a Triangle.

Returns:
The backend module. For example, if the backend is numpy, it will return the “np” that you
would get if you ran the statement, “import numpy as np”.
grain(grain='', trailing=False, inplace=False)[source]#

Changes the grain of a cumulative triangle.

Parameters:
grainstr

The grain to which you want your triangle converted, specified as ‘OXDY’ where X and Y can take on values of ['Y', 'S', 'Q', 'M' ] For example, ‘OYDY’ for Origin Year/Development Year, ‘OQDM’ for Origin quarter/Development Month, etc.

trailingbool

For partial origin years/quarters, trailing will set the year/quarter end to that of the latest available from the origin data.

inplacebool

Whether to mutate the existing Triangle instance or return a new one.

Returns:
Triangle

Examples

Build a quarterly origin / quarterly development Triangle (OQDQ).

import pandas as pd

df = pd.DataFrame(
    data={
        'origin': [
            '2022Q1', '2022Q1', '2022Q1', '2022Q1', '2022Q1', '2022Q1', '2022Q1', '2022Q1',
            '2022Q2', '2022Q2', '2022Q2', '2022Q2', '2022Q2', '2022Q2', '2022Q2',
            '2022Q3', '2022Q3', '2022Q3', '2022Q3', '2022Q3', '2022Q3',
            '2022Q4', '2022Q4', '2022Q4', '2022Q4', '2022Q4',
            '2023Q1', '2023Q1', '2023Q1', '2023Q1',
            '2023Q2', '2023Q2', '2023Q2',
            '2023Q3', '2023Q3',
            '2023Q4',
        ],
        'development': [
            '2022Q1', '2022Q2', '2022Q3', '2022Q4', '2023Q1', '2023Q2', '2023Q3', '2023Q4',
            '2022Q2', '2022Q3', '2022Q4', '2023Q1', '2023Q2', '2023Q3', '2023Q4',
            '2022Q3', '2022Q4', '2023Q1', '2023Q2', '2023Q3', '2023Q4',
            '2022Q4', '2023Q1', '2023Q2', '2023Q3', '2023Q4',
            '2023Q1', '2023Q2', '2023Q3', '2023Q4',
            '2023Q2', '2023Q3', '2023Q4',
            '2023Q3', '2023Q4',
            '2023Q4',
        ],
        'reported': [
            100, 200, 300, 400, 480, 540, 580, 600,
            110, 220, 320, 420, 500, 560, 600,
            120, 240, 350, 450, 520, 580,
            130, 250, 370, 470, 540,
            140, 260, 380, 480,
            150, 270, 390,
            160, 280,
            170,
        ],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=True,
)
print(tr)
           3      6      9      12     15     18     21     24
2022Q1  100.0  200.0  300.0  400.0  480.0  540.0  580.0  600.0
2022Q2  110.0  220.0  320.0  420.0  500.0  560.0  600.0    NaN
2022Q3  120.0  240.0  350.0  450.0  520.0  580.0    NaN    NaN
2022Q4  130.0  250.0  370.0  470.0  540.0    NaN    NaN    NaN
2023Q1  140.0  260.0  380.0  480.0    NaN    NaN    NaN    NaN
2023Q2  150.0  270.0  390.0    NaN    NaN    NaN    NaN    NaN
2023Q3  160.0  280.0    NaN    NaN    NaN    NaN    NaN    NaN
2023Q4  170.0    NaN    NaN    NaN    NaN    NaN    NaN    NaN

Convert to annual origin / annual development. Origins are summed within each calendar year and development periods are aggregated to year-end.

print(tr.grain('OYDY'))
          12      24
2022  1090.0  2320.0
2023  1320.0     NaN

Convert origin to annual but keep development quarterly (OYDQ).

print(tr.grain('OYDQ'))
         3      6      9       12      15      18      21      24
2022  100.0  310.0  640.0  1090.0  1500.0  1860.0  2130.0  2320.0
2023  140.0  410.0  810.0  1320.0     NaN     NaN     NaN     NaN
groupby(by, axis=0, *args, **kwargs)[source]#

Group Triangle by index values. If the triangle is convertable to a DataFrame, then it defaults to pandas groupby functionality.

Parameters:
by: str or list

The index to group by

Returns:
GroupBy object (pandas or Triangle)
head(n=5)[source]#

Return the first n triangles along the index axis.

Parameters:
nint, default 5

Number of triangles to select.

Returns:
Triangle
heatmap(cmap: str = 'coolwarm', low: float = 0, high: float = 0, axis: int | str = 0, subset: IndexSlice = None) Any[source]#

Color the background in a gradient according to the data in each column (optionally row). Requires matplotlib.

Parameters:
cmapstr or colormap

matplotlib colormap

low, highfloat

compress the range by these values.

axisint or str

The axis along which to apply heatmap

subsetIndexSlice

a valid slice for data to limit the style application to

Returns:
Ipython.display.HTML
hvplot(*args, **kwargs)[source]#

Passthrough of pandas functionality

incr_to_cum(inplace=False)[source]#

Method to convert an incremental triangle into a cumulative triangle.

Parameters:
inplace: bool

Set to True will update the instance data attribute inplace

Returns:
Updated instance of triangle accumulated along the origin

Examples

Construct an incremental triangle and accumulate it along the development axis.

df = pd.DataFrame(
    data={
        'origin': [1981, 1981, 1981, 1981, 1982, 1982, 1982, 1983, 1983, 1984],
        'development': [1981, 1982, 1983, 1984, 1982, 1983, 1984, 1983, 1984, 1984],
        'reported': [5012, 3257, 2638, 898, 106, 4179, 1111, 3410, 5582, 5655],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=False,
)
print(tr)
          12      24      36     48
1981  5012.0  3257.0  2638.0  898.0
1982   106.0  4179.0  1111.0    NaN
1983  3410.0  5582.0     NaN    NaN
1984  5655.0     NaN     NaN    NaN
print(tr.incr_to_cum())
          12      24       36       48
1981  5012.0  8269.0  10907.0  11805.0
1982   106.0  4285.0   5396.0      NaN
1983  3410.0  8992.0      NaN      NaN
1984  5655.0     NaN      NaN      NaN

By default incr_to_cum returns a new Triangle. Pass inplace=True to mutate the calling Triangle instead.

print(tr.is_cumulative)
False
tr.incr_to_cum(inplace=True)
print(tr.is_cumulative)
True
log()[source]#

Return the natural logarithm of each element.

Returns:
Triangle
max(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for max functionality.

maximum(other)[source]#

Element-wise maximum of this Triangle and another operand.

See chainladder.maximum() for parameters, usage, and examples.

mean(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for mean functionality.

median(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for median functionality.

melt(*args, **kwargs)[source]#

Refer to pandas for melt functionality.

min(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for min functionality.

minimum(other)[source]#

Element-wise minimum of this Triangle and another operand.

See chainladder.minimum() for parameters, usage, and examples.

pct_chg(*args, **kwargs)[source]#

Refer to pandas for pct_chg functionality.

pipe(func, *args, **kwargs)[source]#

Apply func(self, *args, **kwargs).

Parameters:
funccallable

Function to apply to the Triangle.

*args

Positional arguments passed to func.

**kwargs

Keyword arguments passed to func.

Returns:
object

The return value of func.

Examples

Keep development periods from 48 onward:

>>> import chainladder as cl
>>> raa = cl.load_sample('raa')
>>> raa.pipe(lambda tri: tri.loc[..., 48:])
pivot(*args, **kwargs)[source]#

Refer to pandas for pivot functionality.

plot(*args, **kwargs)[source]#

Passthrough of pandas functionality

prod(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for prod functionality.

quantile(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for quantile functionality.

reindex(columns=None, fill_value=nan)[source]#

Conform Triangle columns to a new set of labels.

Any column in columns that is not already present is added and filled with fill_value.

Parameters:
columnslist

Column labels for the returned Triangle.

fill_valuefloat, default nan

Value assigned to newly added columns.

Returns:
Triangle
rename(axis: Literal['index', 'columns', 'origin', 'development'] | int, value: list | str | dict) Self[source]#

Alter axes labels.

Parameters:
axis: str or int

A value of 0 <= axis <= 4 corresponding to axes ‘index’, ‘columns’, ‘origin’, ‘development’ respectively. Both the int and str representation can be used.

value: list or str or dict

List of new labels to be assigned to the axis. List must be of same length of the specified axis. Can also be a dictionary for renaming columns

Returns:
Triangle with relabeled axis.
round(decimals=0, *args, **kwargs)[source]#

Round each element to the given number of decimal places.

Uses banker’s rounding (round half to even). For example, (8.5).round(0) returns 8, not 9. For conventional rounding, add a small epsilon before rounding, e.g. (tri + 1e-9).round(0).

Parameters:
decimalsint, default 0

Number of decimal places to round to.

Returns:
Triangle
set_backend(backend: str, inplace: bool = False, deep: bool = False, _warn: bool = True, **kwargs)[source]#

Converts triangle array_backend.

Parameters:
backendstr

Currently supported options are ‘numpy’, ‘sparse’, and ‘cupy’

inplacebool

Whether to mutate the existing Triangle instance or return a new one.

deepbool

Whether to also convert the backend of nested Triangle-like attributes (e.g. fitted estimator components).

_warnbool

Internal flag controlling whether a deprecation warning is emitted. Set to False on internal recursive calls so the warning fires only once, at the user’s call site. Not part of the public API.

Returns:
Triangle with updated array_backend
set_index(value, inplace=False)[source]#

Sets the index of the Triangle

shift(periods=-1, axis=3)[source]#

Shift elements along an axis by desired number of periods.

Data that falls beyond the existing shape of the Triangle is eliminated and new cells default to zero.

Parameters:
periodsint

Number of periods to shift. Can be positive or negative.

axis{2 or ‘origin’, 3 or ‘development’, None}, default 3

Shift direction.

Returns:
Triangle

updated with shifted elements

Examples

import pandas as pd
df = pd.DataFrame(
    data={
        'origin': [2020, 2020, 2020, 2021, 2021, 2022],
        'development': [2020, 2021, 2022, 2021, 2022, 2022],
        'reported': [100, 200, 300, 110, 220, 120],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=True,
)
print(tr)
         12     24     36
2020  100.0  200.0  300.0
2021  110.0  220.0    NaN
2022  120.0    NaN    NaN

Shift one period along the development axis (the default). Values move right by one column and the leading column is filled with zeros.

print(tr.shift())
       12     24     36
2020  0.0  100.0  200.0
2021  0.0  110.0  220.0
2022  0.0  120.0    NaN

Shift one period along the origin axis. Each origin row’s data moves down by one and the first origin row is zeroed out.

print(tr.shift(periods=-1, axis='origin'))
         12     24     36
2020    0.0    0.0    0.0
2021  100.0  200.0  300.0
2022  110.0  220.0    NaN
sort_axis(axis)[source]#

Method to sort a Triangle along a given axis

Parameters:
axisint or str

The axis on which to sort. May be specified as an integer (0, 1, 2, 3) or by name ('index', 'columns', 'origin', 'development').

Returns:
Triangle

New Triangle with the requested axis sorted in ascending order.

Examples

Build a Triangle with two columns supplied in non-alphabetical order.

df = pd.DataFrame(
    data={
        'origin': [2020, 2020, 2021, 2021],
        'development': [2020, 2021, 2021, 2021],
        'reported': [100, 200, 110, 110],
        'paid': [50, 100, 60, 60],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported', 'paid'],
    cumulative=True,
)
print(list(tr.columns))
['reported', 'paid']

Sorting on the columns axis returns a new Triangle with columns in alphabetical order.

print(list(tr.sort_axis('columns').columns))
['paid', 'reported']
sort_index(*args, **kwargs)[source]#

Sort Triangle rows by index labels.

Returns:
Triangle
sqrt()[source]#

Return the non-negative square root of each element.

Returns:
Triangle
std(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for std functionality.

sum(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for sum functionality.

tail(n=5)[source]#

Return the last n triangles along the index axis.

Parameters:
nint, default 5

Number of triangles to select.

Returns:
Triangle
to_clipboard(*args, **kwargs)[source]#

Refer to pandas for to_clipboard functionality.

to_csv(*args, **kwargs)[source]#

Refer to pandas for to_csv functionality.

to_dict(*args, **kwargs)[source]#

Refer to pandas for to_dict functionality.

to_excel(*args, **kwargs)[source]#

Refer to pandas for to_excel functionality.

to_frame(origin_as_datetime: bool = True, keepdims: bool = False, implicit_axis: bool = False) DataFrame | Series[source]#

Converts a triangle to a pandas.DataFrame.

Parameters:
origin_as_datetimebool (default = True)

When all dimensions are returned, whether the origin vector should be converted from PeriodIndex into a datetime dtype.

keepdimsbool (default = False)

Converted DataFrame will keep all dimensions intact and maintain a consistent format regardless of whether any dimensions are of length 1.

Ignored when 3 or more dimensions (index, column, origin, and development) have lengths greater than 1

implicit_axisbool (default = False)

When implicit_axis is True, this denotes whether to include the implicit valuation axis in addition to the origin and development.

Returns:
DataFrame or Series representation of the Triangle.
to_html(*args, **kwargs)[source]#

Refer to pandas for to_html functionality.

to_json()[source]#

Serializes triangle object to json format

Returns:
string representation of object in json format
to_pickle(path, protocol=None)[source]#

Serializes triangle object to pickle.

Parameters:
pathstr

File path and name of pickle object.

protocol

The pickle protocol to use.

trend(trend=0.0, axis='origin', start=None, end=None, ultimate_lag=None, **kwargs)[source]#

Allows for the trending of a Triangle object along either a valuation or origin axis. This method trends using days and assumes a years is 365.25 days long.

Parameters:
trendfloat

The annual amount of the trend. Use 1/(1+trend)-1 to detrend.

axisstr (options: [‘origin’, ‘valuation’])

The axis on which to apply the trend

start: date

The start date from which trend should be calculated. If none is provided then the latest date of the triangle is used.

end: date

The end date to which the trend should be calculated. If none is provided then the earliest period of the triangle is used.

ultimate_lagint

If ultimate valuations are in the triangle, optionally set the overall age (in months) of the ultimate to be some lag from the latest non-Ultimate development

Returns:
Triangle

updated with multiplicative trend applied.

Examples

import pandas as pd

df = pd.DataFrame(
    data={
        'origin': [2020, 2020, 2020, 2021, 2021, 2022],
        'development': [2020, 2021, 2022, 2021, 2022, 2022],
        'reported': [100, 200, 300, 110, 220, 120],
    }
)
tr = cl.Triangle(
    data=df,
    origin='origin',
    development='development',
    columns=['reported'],
    cumulative=True,
)
print(tr)
         12     24     36
2020  100.0  200.0  300.0
2021  110.0  220.0    NaN
2022  120.0    NaN    NaN

Apply a 10% annual trend along the origin axis. The latest origin year (2022) is unchanged; older origins are scaled up by 1.10 per year of distance from the latest origin.

print(tr.trend(0.10, axis='origin'))
         12     24     36
2020  121.0  242.0  363.0
2021  121.0  242.0    NaN
2022  120.0    NaN    NaN

Apply a 10% annual trend along the valuation axis instead. The latest diagonal is unchanged and earlier diagonals are scaled up.

print(tr.trend(0.10, axis='valuation'))
         12     24     36
2020  121.0  220.0  300.0
2021  121.0  220.0    NaN
2022  120.0    NaN    NaN
unstack(*args, **kwargs)[source]#

Refer to pandas for unstack functionality.

val_to_dev(inplace=False)[source]#

Converts triangle from a valuation triangle to a development lag triangle.

Parameters:
inplacebool

Whether to mutate the existing Triangle instance or return a new one.

Returns:
Updated instance of triangle with development lags

Examples

val_to_dev is the inverse of dev_to_val. Round-tripping a development triangle through valuation form and back returns the original layout.

tr = cl.load_sample('ukmotor')
print(tr.dev_to_val().val_to_dev())
          12      24       36       48       60       72       84
2007  3511.0  6726.0   8992.0  10704.0  11763.0  12350.0  12690.0
2008  4001.0  7703.0   9981.0  11161.0  12117.0  12746.0      NaN
2009  4355.0  8287.0  10233.0  11755.0  12993.0      NaN      NaN
2010  4295.0  7750.0   9773.0  11093.0      NaN      NaN      NaN
2011  4150.0  7897.0  10217.0      NaN      NaN      NaN      NaN
2012  5102.0  9650.0      NaN      NaN      NaN      NaN      NaN
2013  6283.0     NaN      NaN      NaN      NaN      NaN      NaN
valuation_correlation(p_critical=0.1, total=False)[source]#

Mack test for calendar year effect A calendar period has impact across developments if the probability of the number of small (or large) development factors in that period occurring randomly is less than p_critical

Parameters:
p_critical: float (default=0.10)

Value between 0 and 1 representing the confidence level for the test

total:

Whether to calculate valuation correlation in total across all years (True) consistent with Mack 1993 or for each year separately (False) consistent with Mack 1997.

Returns
——-

ValuationCorrelation object with z, z_critical, z_expectation and z_variance attributes.

Examples

tr = cl.load_sample('raa')
vc = tr.valuation_correlation()
print(vc.z_critical)
       1982   1983   1984   1985   1986   1987   1988   1989   1990
1981  False  False  False  False  False  False  False  False  False

Each cell of z_critical flags whether the calendar-period z-statistic for that valuation falls outside the no-effect confidence interval. False everywhere means no calendar period shows a significant large-or-small bias on its diagonal.

var(axis: str | int | None = None, *args, **kwargs) Triangle | ndarray[source]#

Refer to pandas for var functionality.

xs(index_key: IndexLabel, level: IndexLabel | None = None, drop_level: bool = True)[source]#

Mimics xs from pandas. key difference is that this function only slices the index, therefore axis is always 0 and not an argument in the function

Main use case for this function is when slicing beyond the first field in the index (such as LOB in the clrd dataset)