Dados referentes ao número de sinistros registrados por 16483 clientes de uma seguradora de automóveis ao longo de um ano, contemplando as seguintes variáveis:
- Sinistros: Número de sinistros registrados;
- Exposicao: Período de cobertura do cliente durante o ano sob análise;
- Idade: Idade do cliente (em anos);
- Sexo: M para masculino e F para feminino;
- Valor: Valor do veículo segurado (em reais).
# Pacotes necessários.
library(lattice)
library(MASS)
library(effects)
library(knitr)
library(MRDCr)
Verificação do conteúdo e a estrutura dos dados
# Dez primeiras linhas da base.
head(seguros, 10)
## tipo idade sexo civil valor expos nsinist
## 1 hatch 59 F Casado 24.624 0.50 1
## 2 mono 45 M Solteiro 23.391 0.70 0
## 3 suv 42 M Casado 86.639 0.79 0
## 4 sedan 63 F Casado 77.545 0.01 0
## 5 mono 36 F Casado 25.934 0.51 0
## 6 hatch 33 M Casado 42.704 0.79 0
## 7 hatch 35 M Casado 16.986 0.81 0
## 8 sedan 63 M Casado 19.055 0.01 0
## 9 suv 54 M Casado 52.374 0.76 0
## 10 suv 32 M Casado 52.524 0.79 0
str(seguros)
## 'data.frame': 16483 obs. of 7 variables:
## $ tipo : Factor w/ 6 levels "hatch","mono",..: 1 2 5 4 2 1 1 4 5 5 ...
## $ idade : int 59 45 42 63 36 33 35 63 54 32 ...
## $ sexo : Factor w/ 2 levels "F","M": 1 2 2 1 1 2 2 2 2 2 ...
## $ civil : Factor w/ 4 levels "Casado","Divorciado",..: 1 3 1 1 1 1 1 1 1 1 ...
## $ valor : num 24.6 23.4 86.6 77.5 25.9 ...
## $ expos : num 0.5 0.7 0.79 0.01 0.51 0.79 0.81 0.01 0.76 0.79 ...
## $ nsinist: int 1 0 0 0 0 0 0 0 0 0 ...
seguros$lexpo <- log(seguros$expos)
Análise descritiva da distribuição do número de sinistros
# Distribuição do números de sinistros.
tb <- table(seguros$nsinist)
tb
##
## 0 1 2 3 4 5
## 15689 602 166 22 3 1
barchart(tb, horizontal = FALSE)

# Taxa de sinistros na amostra.
taxageral <- sum(seguros$nsinist)/sum(seguros$expos)
taxageral
## [1] 0.09517499
tab <- aggregate(cbind(expos, nsinist) ~ sexo,
data = seguros, FUN = sum)
taxa <- with(tab, nsinist/expos)
tab <- cbind(tab, taxa)
# Distribuição do número de sinistros por sexo.
kable(tab, align = "c",
caption = "**Taxa de sinistros segundo sexo**")
Taxa de sinistros segundo sexo
F |
4363.92 |
461 |
0.1056390 |
M |
6321.66 |
556 |
0.0879516 |
seguros$idadecat <- cut(seguros$idade,
breaks = c(18, 30, 60, 92),
include.lowest = TRUE)
tab <- aggregate(cbind(expos, nsinist) ~ idadecat,
data = seguros, FUN = sum)
taxa <- with(tab, nsinist/expos)
tab <- cbind(tab, taxa)
# Distribuição do número de sinistros por sexo.
kable(tab, align = "c",
caption = "**Taxa de sinistros segundo idade**")
Taxa de sinistros segundo idade
[18,30] |
462.91 |
46 |
0.0993714 |
(30,60] |
6909.21 |
661 |
0.0956694 |
(60,92] |
3311.64 |
310 |
0.0936092 |
tabidsex <- aggregate(cbind(expos, nsinist) ~ sexo + idadecat,
data = seguros, FUN = sum)
taxa <- with(tabidsex, nsinist/expos)
tabidsex <- cbind(tabidsex, taxa)
# Distribuição do número de sinistros por idade e sexo.
kable(tabidsex, align = "c",
caption = "**Taxa de sinistros segundo sexo e idade**")
Taxa de sinistros segundo sexo e idade
F |
[18,30] |
273.34 |
29 |
0.1060950 |
M |
[18,30] |
189.57 |
17 |
0.0896766 |
F |
(30,60] |
3035.82 |
318 |
0.1047493 |
M |
(30,60] |
3873.39 |
343 |
0.0885529 |
F |
(60,92] |
1054.74 |
114 |
0.1080835 |
M |
(60,92] |
2256.90 |
196 |
0.0868448 |
Regressão usando o modelo log-linear Poisson
seguros <- na.omit(seguros)
mP <- glm(nsinist ~ sexo + idade + I(idade^2) + valor +
offset(log(expos)),
data = seguros, family = poisson)
summary(mP)
##
## Call:
## glm(formula = nsinist ~ sexo + idade + I(idade^2) + valor + offset(log(expos)),
## family = poisson, data = seguros)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.5778 -0.3935 -0.3646 -0.2971 5.2731
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.4583436 0.3809057 -3.829 0.000129 ***
## sexoM -0.1796330 0.0638541 -2.813 0.004905 **
## idade -0.0374658 0.0149912 -2.499 0.012448 *
## I(idade^2) 0.0003276 0.0001416 2.314 0.020644 *
## valor 0.0057360 0.0014905 3.848 0.000119 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 6530.2 on 16478 degrees of freedom
## Residual deviance: 6502.0 on 16474 degrees of freedom
## AIC: 8229
##
## Number of Fisher Scoring iterations: 6
# Estimação do parâmetro de dispersão.
X2 <- sum(resid(mP, type = "pearson")^2)
phichap <- X2/mP$df.residual
# Indicador de superdispersão.
phichap
## [1] 2.518473
envelope <- function(modelo) {
dados <- na.omit(modelo$data)
nsim <- 100
n <- modelo$df.null + 1
r1 <- sort(rstandard(modelo, type = "deviance"))
m1 <- matrix(0, nrow = n, ncol = nsim)
a2 <- simulate(modelo, nsim = nsim)
for (i in 1:nsim) {
dados$y <- a2[, i]
aj <- update(modelo, y ~ ., data = dados)
m1[, i] <- sort(rstandard(aj, type = "deviance"))
}
li <- apply(m1, 1, quantile, 0.025)
m <- apply(m1, 1, quantile, 0.5)
ls <- apply(m1, 1, quantile, 0.975)
quantis <- qnorm((1:n - 0.5)/n)
plot(rep(quantis, 2), c(li, ls), type = "n",
xlab = "Percentil da N(0,1)",
ylab = "Resíduos")
title("Gráfico Normal de Probabilidades")
lines(quantis, li, type = "l")
lines(quantis, m, type = "l", lty = 2)
lines(quantis, ls, type = "l")
points(quantis, r1, pch = 16, cex = 0.75)
}
Diagnóstico do ajuste (gráficos)
# Diagnóstico do modelo - gráficos.
par(mfrow = c(2, 2))
plot(mP)

par(mfrow = c(1, 1))
envelope(mP)

Ajuste do modelo associando um parâmetro ao termo offset (log-exposicao)
mPo <- glm(nsinist ~ sexo + idade + I(idade^2) + valor +
log(expos),
data = seguros, family = poisson)
summary(mPo)
##
## Call:
## glm(formula = nsinist ~ sexo + idade + I(idade^2) + valor + log(expos),
## family = poisson, data = seguros)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.5068 -0.3714 -0.3489 -0.3284 5.4639
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.8967565 0.3819147 -4.966 6.82e-07 ***
## sexoM -0.1888165 0.0638419 -2.958 0.00310 **
## idade -0.0327982 0.0149723 -2.191 0.02848 *
## I(idade^2) 0.0003002 0.0001414 2.123 0.03376 *
## valor 0.0045550 0.0014881 3.061 0.00221 **
## log(expos) 0.1865318 0.0410945 4.539 5.65e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 6319.8 on 16478 degrees of freedom
## Residual deviance: 6275.2 on 16473 degrees of freedom
## AIC: 8004.2
##
## Number of Fisher Scoring iterations: 6
anova(mP, mPo, test = "Chisq")
## Analysis of Deviance Table
##
## Model 1: nsinist ~ sexo + idade + I(idade^2) + valor + offset(log(expos))
## Model 2: nsinist ~ sexo + idade + I(idade^2) + valor + log(expos)
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 16474 6502.0
## 2 16473 6275.2 1 226.78 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Regressão usando a distribuição binomial negativa
mBNo <- glm.nb(nsinist ~ sexo + idade + I(idade^2) + valor +
log(expos), data = seguros)
summary(mBNo)
##
## Call:
## glm.nb(formula = nsinist ~ sexo + idade + I(idade^2) + valor +
## log(expos), data = seguros, init.theta = 0.1203144242, link = log)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.4198 -0.3306 -0.3141 -0.2984 2.6758
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.8575829 0.4809945 -3.862 0.000112 ***
## sexoM -0.1897891 0.0791377 -2.398 0.016475 *
## idade -0.0342408 0.0188090 -1.820 0.068690 .
## I(idade^2) 0.0003144 0.0001774 1.772 0.076428 .
## valor 0.0045735 0.0018819 2.430 0.015086 *
## log(expos) 0.1957247 0.0480051 4.077 4.56e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Negative Binomial(0.1203) family taken to be 1)
##
## Null deviance: 3201.7 on 16478 degrees of freedom
## Residual deviance: 3170.7 on 16473 degrees of freedom
## AIC: 7430.7
##
## Number of Fisher Scoring iterations: 1
##
##
## Theta: 0.1203
## Std. Err.: 0.0105
##
## 2 x log-likelihood: -7416.7460
Diagnóstico do ajuste
# Diagnóstico do modelo - gráficos.
par(mfrow = c(2, 2))
plot(mBNo)

dadosnb3 <-
seguros[, c("sexo", "idade", "valor", "expos", "nsinist")]
dadosnb3$lexpo <- log(seguros$expos)
mBNo <- glm.nb(nsinist ~ sexo + idade + I(idade^2) +
valor + lexpo,
data = dadosnb3)
envelope <- function(modelo) {
dados <- na.omit(dadosnb3)
nsim <- 100
n <- modelo$df.null + 1
r1 <- sort(rstandard(modelo, type = "deviance"))
m1 <- matrix(0, nrow = n, ncol = nsim)
a2 <- simulate(modelo, nsim = nsim)
for (i in 1:nsim) {
dados$y <- a2[, i]
aj <- update(modelo, y ~ ., data = dados)
m1[, i] <- sort(rstandard(aj, type = "deviance"))
}
li <- apply(m1, 1, quantile, 0.025)
m <- apply(m1, 1, quantile, 0.5)
ls <- apply(m1, 1, quantile, 0.975)
quantis <- qnorm((1:n - 0.5)/n)
plot(rep(quantis, 2), c(li, ls), type = "n",
xlab = "Percentil da N(0,1)",
ylab = "Resíduos")
title("Gráfico Normal de Probabilidades")
lines(quantis, li, type = "l")
lines(quantis, m, type = "l", lty = 2)
lines(quantis, ls, type = "l")
points(quantis, r1, pch = 16, cex = 0.75)
}
par(mfrow = c(1, 1))
envelope(mBNo)

Explorando os efeitos das covariáveis
intervalos <- confint(mBNo)
## Waiting for profiling to be done...
estimat <- cbind(mBNo$coefficients, intervalos)
colnames(estimat)[1] <- "Estimativa pontual"
# Quadro de estimativas
kable(round(estimat, 5), align = "c",
caption = paste("**Estimativas pontuais e intervalos de",
"confiança - Modelo Binomial Negativo**"))
Estimativas pontuais e intervalos de confiança - Modelo Binomial Negativo
(Intercept) |
-1.85758 |
-2.81686 |
-0.90742 |
sexoM |
-0.18979 |
-0.34453 |
-0.03493 |
idade |
-0.03424 |
-0.07148 |
0.00332 |
I(idade^2) |
0.00031 |
-0.00004 |
0.00067 |
valor |
0.00457 |
0.00078 |
0.00835 |
lexpo |
0.19572 |
0.10164 |
0.29403 |
Gráficos de efeitos
efeitos <- allEffects(mBNo, given.values = c(lexpo = 0))
plot(efeitos[[2]],
type = "response",
main = "Taxa de sinistros vs. idade",
xlab = "Idade (anos)",
ylab = "Taxa de sinistros")

plot(efeitos[[1]],
type = "response",
main = "Taxa de sinistros vs. sexo",
xlab = "Sexo",
ylab = "Taxa de sinistros")

plot(efeitos[[4]],
type = "response",
main = "Taxa de sinistros vs. valor do automóvel",
xlab = "Valor (x1000 reais)",
ylab = "Taxa de sinistros")

dev.off()
## null device
## 1
Frequências ajustadas pelas duas distribuições
# Poisson sem ajuste de covariáveis.
n <- nrow(seguros)
mediasin <- mean(seguros$nsinist)
freqps <- round(n * dpois(0:10, mediasin))
# Poisson com covariaveis
pred1 <- predict(mPo, type = "response")
intervalo <- 0:10
matprob <- matrix(0, nrow = nrow(seguros), ncol = length(intervalo))
probpois <- function(interv, taxa) dpois(intervalo, taxa)
for (i in 1:nrow(seguros)) {
matprob[i, ] <- probpois(interv = intervalo, taxa = pred1[i])
}
pbarra <- colMeans(matprob)
freqpsaj <- round(n * pbarra)
# Binomial negativa sem covariaveis.
ajustenb <- glm.nb(nsinist ~ 1, data = seguros)
media <- exp(coefficients(ajustenb))
shape <- ajustenb$theta
freqbn <- round(n * dnbinom(0:10, mu = media, size = shape))
# Binomial negativa com covariaveis
pred2 <- predict(mBNo, type = "response")
intervalo <- 0:10
matprob <- matrix(0, nrow = nrow(seguros), ncol = length(intervalo))
probnb <- function(interv, media, shape) {
dnbinom(intervalo, mu = media,
size = shape)
}
for (i in 1:nrow(seguros)) {
matprob[i, ] <- probnb(interv = intervalo, media = pred2[i],
shape = mBNo$theta)
}
pbarra <- colMeans(matprob)
frebnaj <- round(n * pbarra)
ams <- c(table(seguros$nsinist), rep(0, 5))
matfreq <- rbind(ams, freqps, freqpsaj, freqbn, frebnaj)
colnames(matfreq) <- 0:10
rownames(matfreq) <- c("Amostra",
"Poisson não ajustada por covariáveis",
"Poisson ajustada por covariáveis",
"BN não ajustada por covariáveis",
"BN ajustada por covariáveis")
Comparação dos ajustes
kable(matfreq, format = "markdown",
caption = paste("Frequências amostrais e frequências",
"ajustadas para o número de sinistros"))
Amostra |
15685 |
602 |
166 |
22 |
3 |
1 |
0 |
0 |
0 |
0 |
0 |
Poisson não ajustada por covariáveis |
15493 |
956 |
30 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Poisson ajustada por covariáveis |
15494 |
954 |
31 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
BN não ajustada por covariáveis |
15683 |
632 |
122 |
30 |
8 |
2 |
1 |
0 |
0 |
0 |
0 |
BN ajustada por covariáveis |
15683 |
633 |
121 |
30 |
8 |
2 |
1 |
0 |
0 |
0 |
0 |