Triangle Visualization#
Chainladder’s Styler class enables visual customization of triangles when displayed in a Jupyter notebook. Any styling options that can be applied to a Pandas DataFrame can also be applied to a Chainladder Triangle. In addition, the Styler extends its Pandas counterpart with methods designed for actuaries.
Note
The Styler only works on single triangles.
Highlighting the lower triangle#
The lower triangle contains cells that extend beyond the latest diagonal. This area can be highlited with Triangle.style.highlight_lower_triangle().
import chainladder as cl
raa = cl.load_sample("raa")
raa.style.highlight_lower_triangle(color="blue")
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1981 | 5,012 | 8,269 | 10,907 | 11,805 | 13,539 | 16,181 | 18,009 | 18,608 | 18,662 | 18,834 |
| 1982 | 106 | 4,285 | 5,396 | 10,666 | 13,782 | 15,599 | 15,496 | 16,169 | 16,704 | |
| 1983 | 3,410 | 8,992 | 13,873 | 16,141 | 18,735 | 22,214 | 22,863 | 23,466 | ||
| 1984 | 5,655 | 11,555 | 15,766 | 21,266 | 23,425 | 26,083 | 27,067 | |||
| 1985 | 1,092 | 9,565 | 15,836 | 22,169 | 25,955 | 26,180 | ||||
| 1986 | 1,513 | 6,445 | 11,702 | 12,935 | 15,852 | |||||
| 1987 | 557 | 4,020 | 10,946 | 12,314 | ||||||
| 1988 | 1,351 | 6,947 | 13,112 | |||||||
| 1989 | 3,133 | 5,395 | ||||||||
| 1990 | 2,063 |
You may find that the blue contrasts too sharply against the white background of this website. You can change the color to a lighter shade of blue, and the text to white to improve readability.
full = cl.Chainladder().fit(raa).full_triangle_
full.style.highlight_lower_triangle(
color="#2F61AD",
text_color="#FFFFFF",
)
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | 132 | 9999 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1981 | 5,012 | 8,269 | 10,907 | 11,805 | 13,539 | 16,181 | 18,009 | 18,608 | 18,662 | 18,834 | 18,834 | 18,834 |
| 1982 | 106 | 4,285 | 5,396 | 10,666 | 13,782 | 15,599 | 15,496 | 16,169 | 16,704 | 16,858 | 16,858 | 16,858 |
| 1983 | 3,410 | 8,992 | 13,873 | 16,141 | 18,735 | 22,214 | 22,863 | 23,466 | 23,863 | 24,083 | 24,083 | 24,083 |
| 1984 | 5,655 | 11,555 | 15,766 | 21,266 | 23,425 | 26,083 | 27,067 | 27,967 | 28,441 | 28,703 | 28,703 | 28,703 |
| 1985 | 1,092 | 9,565 | 15,836 | 22,169 | 25,955 | 26,180 | 27,278 | 28,185 | 28,663 | 28,927 | 28,927 | 28,927 |
| 1986 | 1,513 | 6,445 | 11,702 | 12,935 | 15,852 | 17,649 | 18,389 | 19,001 | 19,323 | 19,501 | 19,501 | 19,501 |
| 1987 | 557 | 4,020 | 10,946 | 12,314 | 14,428 | 16,064 | 16,738 | 17,294 | 17,587 | 17,749 | 17,749 | 17,749 |
| 1988 | 1,351 | 6,947 | 13,112 | 16,664 | 19,525 | 21,738 | 22,650 | 23,403 | 23,800 | 24,019 | 24,019 | 24,019 |
| 1989 | 3,133 | 5,395 | 8,759 | 11,132 | 13,043 | 14,521 | 15,130 | 15,634 | 15,898 | 16,045 | 16,045 | 16,045 |
| 1990 | 2,063 | 6,188 | 10,046 | 12,767 | 14,959 | 16,655 | 17,353 | 17,931 | 18,234 | 18,402 | 18,402 | 18,402 |
Highlighting diagonals#
Diagonals represent cells sharing the same valuation date. The latest diagonal can be highlighted with Triangle.style.highlight_diagonal(). You can also specify a particular valuation date, or chain diagonal and lower triangle styling together.
# Highlight the latest diagonal and the lower triangle together
raa.style.highlight_diagonal(color="#FFE599").highlight_lower_triangle(color="#DDEBF7")
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1981 | 5,012 | 8,269 | 10,907 | 11,805 | 13,539 | 16,181 | 18,009 | 18,608 | 18,662 | 18,834 |
| 1982 | 106 | 4,285 | 5,396 | 10,666 | 13,782 | 15,599 | 15,496 | 16,169 | 16,704 | |
| 1983 | 3,410 | 8,992 | 13,873 | 16,141 | 18,735 | 22,214 | 22,863 | 23,466 | ||
| 1984 | 5,655 | 11,555 | 15,766 | 21,266 | 23,425 | 26,083 | 27,067 | |||
| 1985 | 1,092 | 9,565 | 15,836 | 22,169 | 25,955 | 26,180 | ||||
| 1986 | 1,513 | 6,445 | 11,702 | 12,935 | 15,852 | |||||
| 1987 | 557 | 4,020 | 10,946 | 12,314 | ||||||
| 1988 | 1,351 | 6,947 | 13,112 | |||||||
| 1989 | 3,133 | 5,395 | ||||||||
| 1990 | 2,063 |
Applying styles from a Triangle#
For custom styling patterns, Triangle.style.apply_from_triangle() allows you to style cells based on a mask Triangle. Cells where the mask has non-missing (or truthy) values are highlighted.
For example, you can highlight cells by slicing a Triangle:
# Highlight the latest diagonal via valuation slicing
raa.style.apply_from_triangle(
raa[raa.valuation == raa.valuation_date],
color="#FFE599",
)
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1981 | 5,012 | 8,269 | 10,907 | 11,805 | 13,539 | 16,181 | 18,009 | 18,608 | 18,662 | 18,834 |
| 1982 | 106 | 4,285 | 5,396 | 10,666 | 13,782 | 15,599 | 15,496 | 16,169 | 16,704 | |
| 1983 | 3,410 | 8,992 | 13,873 | 16,141 | 18,735 | 22,214 | 22,863 | 23,466 | ||
| 1984 | 5,655 | 11,555 | 15,766 | 21,266 | 23,425 | 26,083 | 27,067 | |||
| 1985 | 1,092 | 9,565 | 15,836 | 22,169 | 25,955 | 26,180 | ||||
| 1986 | 1,513 | 6,445 | 11,702 | 12,935 | 15,852 | |||||
| 1987 | 557 | 4,020 | 10,946 | 12,314 | ||||||
| 1988 | 1,351 | 6,947 | 13,112 | |||||||
| 1989 | 3,133 | 5,395 | ||||||||
| 1990 | 2,063 |
Numeric Formatting#
The Styler allows you to control the numeric format of a Triangle’s values. Let’s change the precision of the link ratios to have 3 decimal places.
raa.link_ratio.style.format(
precision=3,
na_rep="",
)
| 12-24 | 24-36 | 36-48 | 48-60 | 60-72 | 72-84 | 84-96 | 96-108 | 108-120 | |
|---|---|---|---|---|---|---|---|---|---|
| 1981 | 1.650 | 1.319 | 1.082 | 1.147 | 1.195 | 1.113 | 1.033 | 1.003 | 1.009 |
| 1982 | 40.425 | 1.259 | 1.977 | 1.292 | 1.132 | 0.993 | 1.043 | 1.033 | |
| 1983 | 2.637 | 1.543 | 1.163 | 1.161 | 1.186 | 1.029 | 1.026 | ||
| 1984 | 2.043 | 1.364 | 1.349 | 1.102 | 1.113 | 1.038 | |||
| 1985 | 8.759 | 1.656 | 1.400 | 1.171 | 1.009 | ||||
| 1986 | 4.260 | 1.816 | 1.105 | 1.226 | |||||
| 1987 | 7.217 | 2.723 | 1.125 | ||||||
| 1988 | 5.142 | 1.887 | |||||||
| 1989 | 1.722 |
Localization#
Chainladder is used by actuaries all over the world. The Styler can be used to adapt the numeric formatting to specific locales. Let’s try formating genins with the Swiss numbering format, which uses apostrophes as the thousands separator.
genins = cl.load_sample("genins")
genins.style.format(
precision=0,
thousands="'",
na_rep="",
)
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 2001 | 357'848 | 1'124'788 | 1'735'330 | 2'218'270 | 2'745'596 | 3'319'994 | 3'466'336 | 3'606'286 | 3'833'515 | 3'901'463 |
| 2002 | 352'118 | 1'236'139 | 2'170'033 | 3'353'322 | 3'799'067 | 4'120'063 | 4'647'867 | 4'914'039 | 5'339'085 | |
| 2003 | 290'507 | 1'292'306 | 2'218'525 | 3'235'179 | 3'985'995 | 4'132'918 | 4'628'910 | 4'909'315 | ||
| 2004 | 310'608 | 1'418'858 | 2'195'047 | 3'757'447 | 4'029'929 | 4'381'982 | 4'588'268 | |||
| 2005 | 443'160 | 1'136'350 | 2'128'333 | 2'897'821 | 3'402'672 | 3'873'311 | ||||
| 2006 | 396'132 | 1'333'217 | 2'180'715 | 2'985'752 | 3'691'712 | |||||
| 2007 | 440'832 | 1'288'463 | 2'419'861 | 3'483'130 | ||||||
| 2008 | 359'480 | 1'421'128 | 2'864'498 | |||||||
| 2009 | 376'686 | 1'363'294 | ||||||||
| 2010 | 344'014 |
Babel#
You can supply a format using the babel package if you have it installed. Let’s try the Indian numeric format.
from babel.numbers import format_decimal
# The Indian numbering system groups by lakh and crore: 12,34,567.
genins.style.format(
lambda x: format_decimal(x, locale="en_IN"),
na_rep="",
)
| 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 | 108 | 120 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 2001 | 3,57,848 | 11,24,788 | 17,35,330 | 22,18,270 | 27,45,596 | 33,19,994 | 34,66,336 | 36,06,286 | 38,33,515 | 39,01,463 |
| 2002 | 3,52,118 | 12,36,139 | 21,70,033 | 33,53,322 | 37,99,067 | 41,20,063 | 46,47,867 | 49,14,039 | 53,39,085 | |
| 2003 | 2,90,507 | 12,92,306 | 22,18,525 | 32,35,179 | 39,85,995 | 41,32,918 | 46,28,910 | 49,09,315 | ||
| 2004 | 3,10,608 | 14,18,858 | 21,95,047 | 37,57,447 | 40,29,929 | 43,81,982 | 45,88,268 | |||
| 2005 | 4,43,160 | 11,36,350 | 21,28,333 | 28,97,821 | 34,02,672 | 38,73,311 | ||||
| 2006 | 3,96,132 | 13,33,217 | 21,80,715 | 29,85,752 | 36,91,712 | |||||
| 2007 | 4,40,832 | 12,88,463 | 24,19,861 | 34,83,130 | ||||||
| 2008 | 3,59,480 | 14,21,128 | 28,64,498 | |||||||
| 2009 | 3,76,686 | 13,63,294 | ||||||||
| 2010 | 3,44,014 |