9.2 Forme des données

Avant de développer les modèles mathématiques, il est pertinent de comprendre la structure des données d’un assureur. Pour un assuré spécifique, les données en assurance ont typiquement la forme suivante:

\(t\) \(\lambda_t\) \(\kappa_t\) \(n_t\) \(x_{t,1}\) \(x_{t,2}\) \(x_{t,3}\) \(s_t\)
1 0.250 5000 3 1000 3500 7500 12,000
2 0.195 7500 0 . . . 0
3 0.125 8625 2 11,500 450 . 11,950

avec:

  • \(t\) représentant le numéro du contrat;
  • \(\lambda_t\) représentant la prime a priori de la composante fréquence pour le contrat \(t\);
  • \(\kappa_t\) représentant la prime a priori de la composante fréquence pour le contrat \(t\);
  • \(n_t\) le nombre de sinistres réclamés pour le contrat \(t\);
  • \(x_{t,j}\) le coût du \(j^e\) sinistre du contrat \(t\);
  • \(s_t = \sum_{j=1}^{n_{t}} x_{t,j}\) la charge totale pour le contrat \(t\).

9.2.1 Fréquence et charge pure

Proposition 9.1 L’historique de réclamations de la fréquence de réclamations des contrats \(1, \ldots, T\) correspond au nombre de réclamations de chacun des \(T\) contrats, et se note \(n_1, \ldots, n_T = n_{(1:T)}\).

Proposition 9.2 L’historique de réclamations de la charge pure des contrats \(1, \ldots, T\) correspond à la charge pure de chacun des \(T\) contrats, et se note \(s_1, \ldots, s_T = s_{(1:T)}\).


9.2.2 Sévérité

Il est un peu plus difficile de trouver une notation concise pour lister toutes les sévérités d’un même assuré. Sur la base de données en entier, nous avons \(\sum_{t=1}^T n_t = n_{\bullet}\) sinistres. Pour lister toutes les réclamations, en divisant par contrat, nous aurons:

  • \(x_{1,1}, x_{1,2} \ldots, x_{1,n_1}\) sévérités pour le premier contrat;
  • \(x_{2,1}, x_{2,2} \ldots, x_{2,n_2}\) sévérités pour le deuxième contrat;
  • \(x_{T,1}, x_{T,2} \ldots, x_{T,n_T}\) sévérités pour le contrat \(T\);

Il est parfois un peu plus difficile de travailler avec un double indice, comme pour la sévérité de la \(j^e\) réclamation du \(t^e\) contrat, noté \(x_{t,j}\).

Ainsi, une stratégie habituellement utilisée en actuariat pour l’analyse de la sévérité est de créer une nouvelle base de données des réclamations, dans laquelle une observation (c’est-à-dire une ligne dans la base de données) correspond à un sinistre. De cette manière, on se retrouve avec une base de données de \(n_{\bullet}\) observations.


Exemple 9.1 On reprend le tableau suivant listant l’expérience de sinistres d’un seul assuré observé sur 3 contrats:

\(t\) \(\lambda_t\) \(\kappa_t\) \(n_t\) \(x_{t,1}\) \(x_{t,2}\) \(x_{t,3}\) \(s_t\)
1 0.250 5000 3 1000 3500 7500 12,000
2 0.195 7500 0 . . . 0
3 0.125 8625 2 11,500 450 . 11,950

Convertissez la base de données en base de données des réclamations.

(Exemple à faire en classe)
\(k\) \(t_k\) \(\kappa_k\) \(x_{k}\)
1 1 5000 1000
2 1 5000 3500
3 1 5000 7500
4 3 8625 11,500
5 3 8625 450

La base de données des réclamations a ainsi \(n_{\bullet} = 5\) observations. Chaque réclamation \(k\) a son contrat \(t_k\) qui lui est associé, de même que la bonne valeur de \(\kappa_k\) qui a été récupérée en associant une réclamation à son contrat \(t\).


Proposition 9.3 L’historique de réclamations de la sévérité des contrats \(1, \ldots, T\) correspond à la sévérité de chacun des \(\sum_{t=1}^T n_t = n_{\bullet}\) sinistres qu’il a eu. En lien avec la bse de données des réclamations, on notera l’historique de réclamations comme \(x_1, \ldots, x_{n_{\bullet}} = x_{(1:n_{\bullet})}\).


Pour conclure, cela signifie que pour la fréquence et la charge totale, nous utilisons \(T\) observations pour mettre à jour notre connaissance de l’hétérogénéité, alors que pour la sévérité, nous utilisons \(n_{\bullet}\) observations.


Cela signifie aussi qu’un assuré n’ayant jamais eu de réclamation, même s’il a été assuré pendant plusieurs année, n’a pas de crédibilité individuelle pour sa sévérité.


9.2.3 Application en R

Dans la base de données utilisées pour supporter la théorie, on peut voir une structure de données assez similaire. Ainsi, pour un véhicule spécifique, nous avons:

db.fictif %>%
  filter(policy_no==6083838 & veh.num == 1) %>%
  arrange(policy_no, veh.num, renewal_date) %>%
  group_by(policy_no, veh.num) %>%
  mutate(contract.no = row_number(),
         Tot.Cost = Cost1+Cost2+Cost3+Cost4) %>%
  select(policy_no, veh.num, contract.no, renewal_date, myopie, cheveux, nb.sin, Cost1, Cost2, Cost3, Cost4, Tot.Cost)
## # A tibble: 8 × 12
## # Groups:   policy_no, veh.num [1]
##   policy_no veh.num contract.no renewal_date myopie cheveux nb.sin  Cost1 Cost2 Cost3 Cost4 Tot.Cost
##       <dbl>   <int>       <int> <date>       <chr>  <chr>    <int>  <dbl> <dbl> <dbl> <dbl>    <dbl>
## 1   6083838       1           1 2011-05-18   Non    Bruns        1   121.    0     0      0     121.
## 2   6083838       1           2 2012-05-18   Non    Bruns        0     0     0     0      0       0 
## 3   6083838       1           3 2013-05-18   Non    Bruns        0     0     0     0      0       0 
## 4   6083838       1           4 2014-05-18   Non    Bruns        0     0     0     0      0       0 
## 5   6083838       1           5 2015-05-18   Non    Bruns        1  1182.    0     0      0    1182.
## 6   6083838       1           6 2016-05-18   Non    Roux         3 20186.  222.  611.     0   21019.
## 7   6083838       1           7 2017-05-18   Non    Bruns        0     0     0     0      0       0 
## 8   6083838       1           8 2018-05-18   Non    Roux         0     0     0     0      0       0

Pour convertir ce jeu de données de fréquence et jeu de données de sévérité, une simple conversion de la base de données peut être faite.


Nous nous intéressons à la sévérité des réclamations. Cela signifie que nous ne considérons pas les assurés qui n’ont pas réclamé.

db <- db.fictif %>%
  filter(nb.sin > 0)

nrow(db)
## [1] 63493
sum(db$nb.sin)
## [1] 73703

Le jeu de données db contient \(63,493\) observations, pour un total de \(73,703\) sinistres. En effet, certains assurés ont plus d’une réclamation par contrat. Il nous faut donc modifier le jeu de données db pour qu’il y ait un sinistre par observation (caractéristique de ce qu’on appelait tidy data au premier chapitre).


La fonction gather du package tidyr crée une nouvelle observation pour chacune des colonnes Cost1 à Cost7. Pour ne pas créer d’observation lorsque les colonnes Cost2 à Cost7 sont nulles, un filtre est ajouté.

library(tidyr)
db <- db %>%
  gather(Rang, Cost, Cost1:Cost7) %>%
  filter(Cost > 0)

nrow(db)
## [1] 73703

Le jeu de données db contient maintenant \(73,703\) observations, soit exactement le nombre de sinistres dans la base de données dbfictif.Rda originale.


Si on reprend le même assuré que plus tôt, nous avons donc la liste des 5 réclamations:

db %>%
  filter(policy_no==6083838 & veh.num == 1) %>%
  arrange(policy_no, veh.num, renewal_date) %>%
  group_by(policy_no, veh.num) %>%
  mutate(claim.no = row_number()) %>%
  select(policy_no, veh.num, claim.no, myopie, cheveux, Cost)
## # A tibble: 5 × 6
## # Groups:   policy_no, veh.num [1]
##   policy_no veh.num claim.no myopie cheveux   Cost
##       <dbl>   <int>    <int> <chr>  <chr>    <dbl>
## 1   6083838       1        1 Non    Bruns     121.
## 2   6083838       1        2 Non    Bruns    1182.
## 3   6083838       1        3 Non    Roux    20186.
## 4   6083838       1        4 Non    Roux      222.
## 5   6083838       1        5 Non    Roux      611.

On peut d’ailleurs noter que les caractéristiques du risques montrées, ici myopie et cheveux, sont correctement associées à chaque réclamation.