The Society of Actuaries (SOA) provides an extensive online database called ‘Mortality and Other Rate Tables’ (‘MORT’) at https://mort.soa.org/. This database contains mortality, lapse, and valuation tables that cover a variety of product types and nations. Users of the database can download any tables in ‘Excel’, ‘CSV’, or ‘XML’ formats. This package provides convenience functions that read ‘XML’ formats from the database and return R objects.
The mortSOA package can be installed from CRAN with:
install.packages("mortSOA")You can install the development version of mortSOA from GitHub with:
# install.packages("pak")
pak::pak("mattheaphy/mortSOA")The mortSOA package comes with a data frame that contains an inventory
of available tables on mort.soa.org. This data set is not
automatically refreshed and was last updated on 2026-01-24.
library(mortSOA)
library(tibble)
table_inventory
#> # A tibble: 3,034 × 6
#> table_id name description layout usage nation
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 1941 CSO Basic Table, ANB "1941 Comm… Aggre… CSO … Unite…
#> 2 2 1941 CSO Experience Table, ANB "1941 Comm… Aggre… CSO … Unite…
#> 3 3 1941 CSO Table with Davis’ Extensio… "1941 Comm… Aggre… CSO … Unite…
#> 4 4 1941 CSO Table with Davis’ Extensio… "1941 Comm… Aggre… CSO … Unite…
#> 5 5 1958 CSO - Male, ANB "1958 Comm… Aggre… CSO … Unite…
#> 6 6 1958 CSO- Female, ANB "1958 Comm… Aggre… CSO … Unite…
#> 7 7 1958 CSO - Male, ALB "1958 Comm… Aggre… CSO … Unite…
#> 8 8 1958 CSO - Female, ALB "1958 Comm… Aggre… CSO … Unite…
#> 9 9 1958 CET - Male, ANB "1958 Comm… Aggre… CSO … Unite…
#> 10 10 1958 CET - Female, ANB "1958 Comm… Aggre… CSO … Unite…
#> # ℹ 3,024 more rowsThe table inventory is provided as a quick reference to look up table
identification numbers used by mort.soa.org. The filter_inventory()
function is provided to assist with searching the inventory.
Let’s assume that we are interested in the 2012 IAM Basic table.
filter_inventory("2012", "IAM Basic")
#> # A tibble: 2 × 6
#> table_id name description layout usage nation
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 2581 2012 IAM Basic Table – Male, ANB 2012 Individu… Aggre… Annu… Unite…
#> 2 2582 2012 IAM Basic Table – Female, ANB 2012 Individu… Aggre… Annu… Unite…The read_mort_soa() function is used to obtain data from
mort.soa.org. This function requires a table identification number
(table_id). Continuing with the prior example, let’s look up table
2582, the 2012 IAM Basic Tables for female lives.
iam_2012_f <- read_mort_soa(2582)
iam_2012_f[[1]]
#> # A tibble: 121 × 2
#> age qx
#> <dbl> <dbl>
#> 1 0 0.00180
#> 2 1 0.00045
#> 3 2 0.000287
#> 4 3 0.000199
#> 5 4 0.000152
#> 6 5 0.000139
#> 7 6 0.00013
#> 8 7 0.000122
#> 9 8 0.000105
#> 10 9 0.000098
#> # ℹ 111 more rowsThis function returns a list of any tables (converted to data frames)
found under the given table_id. Since 2012 IAM basic is an ultimate
table there is only one data frame in the list.
The list includes additional metadata attributes that can be inspected
using the attr() or attributes() functions.
attributes(iam_2012_f)
#> $name
#> [1] "2012 IAM Basic Table – Female, ANB"
#>
#> $table_id
#> [1] "2582"
#>
#> $description
#> [1] "2012 Individual Annuity Mortality Basic Table – Female. Basis: Age Nearest Birthday. Minimum Age: 0. Maximum Age: 120"
#>
#> $usage
#> [1] "Annuitant Mortality"
#>
#> $layout
#> [1] "Aggregate"
#>
#> $nation
#> [1] "United States of America"
#>
#> $sub_descriptions
#> [1] "2012 Individual Annuity Mortality Basic Table – Female. Basis: Age Nearest Birthday. Minimum Age: 0. Maximum Age: 120"Many tables in mort.soa.org have a select and ultimate structure. For
these tables, the list returned by read_mort_soa() will include two
elements. The first element is a two-dimensional table with mortality
rates varying by issue age and policy duration. The second element is an
ultimate mortality table varying by attained age only.
Example using the 2015 VBT Non-Smoker ALB table (table_id = 3269)
vbt <- read_mort_soa(3269)Select table
vbt[[1]]
#> # A tibble: 1,950 × 3
#> age duration qx
#> <dbl> <dbl> <dbl>
#> 1 18 1 0.00066
#> 2 18 2 0.00069
#> 3 18 3 0.00071
#> 4 18 4 0.00071
#> 5 18 5 0.00069
#> 6 18 6 0.00069
#> 7 18 7 0.00068
#> 8 18 8 0.00066
#> 9 18 9 0.00057
#> 10 18 10 0.00052
#> # ℹ 1,940 more rowsUltimate table
vbt[[2]]
#> # A tibble: 103 × 2
#> age qx
#> <dbl> <dbl>
#> 1 18 0.00066
#> 2 19 0.00069
#> 3 20 0.00071
#> 4 21 0.00071
#> 5 22 0.00069
#> 6 23 0.00069
#> 7 24 0.00068
#> 8 25 0.00066
#> 9 26 0.00057
#> 10 27 0.00052
#> # ℹ 93 more rowsThe mortSOA package and its authors are not affiliated with the Society
of Actuaries, which owns and operates mort.soa.org. Review the terms
of use at https://mort.soa.org/TermsOfUse.aspx for more information.