Statistical Software
Study guides: Exam MAS-I, Exam PCPA
Statistical software — a programming language such as R, Python or SAS and the packages built on it — is how data sets are imported, cleaned and reshaped, how models are fitted, and how results reach the analyst: as printed tables of estimates, standard errors and tests that a candidate must be able to read without seeing the code. The CAS names no preferred language: PCPA candidates submit their code in R, Python or SAS, and MAS-I questions may show parameter and diagnostic tables of the kind a language such as R prints, but never ask a candidate to write or interpret R code. The examples below use R and Python.
\texttt{claims} \sim \texttt{territory} + \texttt{age}
\ln \mu_i = \beta_0 + \beta_{\text{terr}(i)} + \beta_{\text{age}}\,\text{age}_i
- Model formulas are shared by R and Python's statsmodels: the response to the left of
~, the predictors to the right. With a Poisson family and log link, the first block specifies the linear predictor in the second, where\beta_{\text{terr}(i)}is the coefficient of policyi's territory (0for the base). A categorical variable expands intok - 1indicator columns of the design matrix;a:bis an interaction anda*bmeans both main effects plus the interaction. The link and distribution come from thefamilyargument, not the formula - R:
read.csv()imports a.csvfile;str()andsummary()report each column's type and summary statistics; the tidyverse verbsfilter(),mutate(),group_by(),summarise(),left_join()andpivot_longer()reshape it into tidy data (Grolemund and Wickham).lm()fits Linear Regression;glm()fits a Generalized Linear Model withfamily = poisson,Gammaorbinomialand anoffset;summary()prints the coefficient table andanova()the analysis of deviance - Python: pandas does the data work —
pd.read_csv(),.dtypes,.describe(),.isna().sum(),.groupby().agg(),.merge(),.melt()(McKinney); statsmodels fitsols()andglm()from the same formula syntax, and.summary()prints the output - Reading the output (Parameter Estimate Tables): each row gives the estimate, its standard error, their ratio and a p-value. In R's
glm()summary the ratio is labelledzwhen the dispersion is fixed (Poisson, binomial) andtwhen it is estimated (Normal, Gamma). The footer gives the null and residual deviance with their degrees of freedom and the AIC; anlm()summary gives the residual standard error, R-Squared and the overallFtest (ANOVA) - Defaults that bite: a categorical variable's base level is its first level — alphabetical unless reset (
relevel()in R) — whereas a rating plan usually wants the level with the most exposure; a category stored as integers is fitted as a number until declared afactor(R) orcategory(pandas); and R's model functions drop rows with a missing value (the summary says how many), so check the observation count against the data
Reading a Frequency GLM Summary A Poisson GLM with a log link and
offset(log(exposure))is fitted in R to1{,}000policies, with territory (A is the base) as its only predictor. Part ofsummary():Estimate Std. Error z value Pr(>|z|) (Intercept) -2.3026 0.0400 -57.57 <2e-16 territoryB 0.2231 0.0600 3.72 0.0002 territoryC -0.1054 0.0700 -1.51 0.1320 Null deviance: 1250.3 on 999 degrees of freedom Residual deviance: 1231.0 on 997 degrees of freedomFind the base frequency and the territory relativities, a
95\%interval for B's relativity, and whether territory as a whole is significant.Answer Exponentiate: base frequency
e^{-2.3026} = 0.100claims per unit of exposure; relativitiese^{0.2231} = 1.250for B ande^{-0.1054} = 0.900for C.\begin{align*} \text{B interval} &= e^{0.2231 \pm 1.96(0.0600)} \\ &= \left(e^{0.1055},\ e^{0.3407}\right) \\ &= (1.111,\ 1.406) \end{align*}B is significantly different from A (
p = 0.0002); C is not (p = 0.132). For the variable as a whole, the null model has the intercept alone, so\begin{align*} \Delta D &= 1{,}250.3 - 1{,}231.0 \\ &= 19.3 \end{align*}on
999 - 997 = 2degrees of freedom, well above\chi^2_{0.05,\,2} = 5.99. Territory belongs in the model even though one of its levels is not individually significant; C might instead be combined with A.
Importing and Summarizing a Policy File
policies.csvhas one row per policy withterritory(coded1,2,3),exposureandclaim_count. Import it, make territory categorical, and tabulate claim frequency by territory in R or Python. The territory totals are2{,}500exposures and150claims,1{,}200and96, and800and36.Answer In R with dplyr:
library(dplyr) pol <- read.csv("policies.csv") str(pol) # territory is read as int pol <- mutate(pol, territory = factor(territory)) pol %>% group_by(territory) %>% summarise(exposure = sum(exposure), claims = sum(claim_count)) %>% mutate(frequency = claims / exposure)In Python with pandas:
import pandas as pd pol = pd.read_csv("policies.csv") pol.dtypes # territory is read as int64 pol["territory"] = pol["territory"].astype("category") out = pol.groupby("territory").agg( exposure=("exposure", "sum"), claims=("claim_count", "sum")) out["frequency"] = out["claims"] / out["exposure"]Either gives frequencies of
150/2{,}500 = 0.060,96/1{,}200 = 0.080and36/800 = 0.045, against282/4{,}500 = 0.0627overall. Before modelling, also check the row count against the source and the count of missing values in each column (colSums(is.na(pol))in R,pol.isna().sum()in pandas). Without the conversion, a GLM would fit territory as one slope across the codes1,2,3.