1 Interaction : deux variables catégorielles

1.1 Récupération des données

On travaille avec un jeu de données simulées très simple, comportant deux variables catégorielles (Sexe et Age), la variable que l’on prendra comme réponse (NbSin), et l’exposition (Exposition), dans le but de réaliser un ajustement GLM log-Poisson. Les données sont groupées par profil de variables explicatives.

load(url("https://irma.math.unistra.fr/~jberard/donnees_glm_sim_inter")) 
str(donnees)
## 'data.frame':    12 obs. of  4 variables:
##  $ Sexe      : Factor w/ 2 levels "F","H": 1 2 1 2 1 2 1 2 1 2 ...
##  $ Age       : Factor w/ 6 levels "18-20","21-23",..: 1 1 2 2 3 3 4 4 5 5 ...
##  $ NbSin     : num  2762 5210 5564 9546 6613 ...
##  $ Exposition: num  29585 22661 69323 48514 87142 ...

1.2 Ajustements avec termes d’interaction entre Sexe et Age

On commence par effectuer un ajustement en traitant les variables Sexe et Age à l’aide d’une interaction “complète”, ce qui revient à traiter le couple (Sexe,Age) comme une unique variable catégorielle. Concrètement, on utilise la fonction interaction pour produire cette variable.

# Ajustement avec interaction complète
ajust_inter_1 <- glm(NbSin ~ interaction(Sexe, Age) + offset(log(Exposition)),
                     family = poisson(link = "log"),
                     data = donnees)
summary(ajust_inter_1)
## 
## Call:
## glm(formula = NbSin ~ interaction(Sexe, Age) + offset(log(Exposition)), 
##     family = poisson(link = "log"), data = donnees)
## 
## Coefficients:
##                               Estimate Std. Error  z value Pr(>|z|)    
## (Intercept)                   -2.37131    0.01903 -124.623  < 2e-16 ***
## interaction(Sexe, Age)H.18-20  0.90126    0.02354   38.291  < 2e-16 ***
## interaction(Sexe, Age)F.21-23 -0.15115    0.02328   -6.494 8.37e-11 ***
## interaction(Sexe, Age)H.21-23  0.74557    0.02161   34.508  < 2e-16 ***
## interaction(Sexe, Age)F.24-33 -0.20719    0.02266   -9.145  < 2e-16 ***
## interaction(Sexe, Age)H.24-33  0.03139    0.02307    1.361    0.174    
## interaction(Sexe, Age)F.34-53 -0.41460    0.02342  -17.702  < 2e-16 ***
## interaction(Sexe, Age)H.34-53 -0.36141    0.02444  -14.789  < 2e-16 ***
## interaction(Sexe, Age)F.53-70 -0.40976    0.02558  -16.020  < 2e-16 ***
## interaction(Sexe, Age)H.53-70 -0.37688    0.02619  -14.388  < 2e-16 ***
## interaction(Sexe, Age)F.>70   -0.65285    0.03207  -20.355  < 2e-16 ***
## interaction(Sexe, Age)H.>70   -0.68223    0.03229  -21.127  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance:  1.1991e+04  on 11  degrees of freedom
## Residual deviance: -1.3323e-13  on  0  degrees of freedom
## AIC: 145.52
## 
## Number of Fisher Scoring iterations: 2
library(outilscoursglm)

On procède ensuite au tracé du terme correspondant dans la composante systématique du modèle, en fonction des deux variables Sexe et Age simultanément, à l’aide de la fonction trace_terme_bivar du fichier d’outils.

trace_terme_bivar(ajustement = ajust_inter_1,
                  nom_terme = "interaction(Sexe, Age)",
                  nom_variable_2 = "Sexe",
                  nom_variable_1 = "Age",
                  trace_exposition = TRUE,
                  nom_exposition = "Exposition",
                  trace_int_conf = TRUE)
## Warning in trace_terme_bivar(ajustement = ajust_inter_1, nom_terme = "interaction(Sexe, Age)", : Utilisation des données de ajustement$data

On traite maintenant les variables Sexe et Age à l’aide d’une interaction “marginale” : chacune des deux variables se voit attribuer des coefficients comme dans le cas purement additif, mais un terme correctif vient s’ajouter pour représenter l’interaction. Concrètement, on utilise un terme de la forme Sexe:Age dans la formule, en plus de la présence individuelle de Sexe et Age afin de produire ce terme. (En l’absence de Sexe et Age, le terme Sexe:Age produirait une interaction complète.) On peut également utiliser une fonction dédiée, telle que inter_marginale dans le fichier d’outils.

# Ajustement avec interaction marginale
ajust_inter_2 <- glm(NbSin ~ Sexe + Age + Sexe:Age + offset(log(Exposition)),
                     family = poisson(link = "log"),
                     data = donnees)
summary(ajust_inter_2)
## 
## Call:
## glm(formula = NbSin ~ Sexe + Age + Sexe:Age + offset(log(Exposition)), 
##     family = poisson(link = "log"), data = donnees)
## 
## Coefficients:
##                 Estimate Std. Error  z value Pr(>|z|)    
## (Intercept)    -2.371309   0.019028 -124.623  < 2e-16 ***
## SexeH           0.901261   0.023537   38.291  < 2e-16 ***
## Age21-23       -0.151151   0.023276   -6.494 8.37e-11 ***
## Age24-33       -0.207194   0.022656   -9.145  < 2e-16 ***
## Age34-53       -0.414604   0.023421  -17.702  < 2e-16 ***
## Age53-70       -0.409761   0.025577  -16.020  < 2e-16 ***
## Age>70         -0.652847   0.032074  -20.355  < 2e-16 ***
## SexeH:Age21-23 -0.004541   0.028956   -0.157    0.875    
## SexeH:Age24-33 -0.662677   0.029585  -22.399  < 2e-16 ***
## SexeH:Age34-53 -0.848064   0.031235  -27.151  < 2e-16 ***
## SexeH:Age53-70 -0.868379   0.034208  -25.385  < 2e-16 ***
## SexeH:Age>70   -0.930643   0.043605  -21.343  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance:  1.1991e+04  on 11  degrees of freedom
## Residual deviance: -9.5479e-14  on  0  degrees of freedom
## AIC: 145.52
## 
## Number of Fisher Scoring iterations: 2

On procède maintenant au tracé des différents termes : d’abord ceux associés individuellement aux variables Sexe et Age (c’est la partie purement additive de la composante systématique du modèle, on parle également d’“effets principaux” des deux variables.)

trace_terme_univar(ajustement = ajust_inter_2,
                   nom_terme = "Sexe",
                   nom_variable = "Sexe",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_2, nom_terme = "Sexe", : Utilisation des données de ajustement$data

trace_terme_univar(ajustement = ajust_inter_2,
                   nom_terme = "Age",
                   nom_variable = "Age",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_2, nom_terme = "Age", : Utilisation des données de ajustement$data

On trace maintenant, en fonction des des deux variables Sexe et Age simultanément, le terme d’interaction marginale.

trace_terme_bivar(ajustement = ajust_inter_2,
                  nom_terme = "Sexe:Age",
                  nom_variable_2 = "Sexe",
                  nom_variable_1 = "Age",
                  trace_exposition = TRUE,
                  nom_exposition = "Exposition",
                  trace_int_conf = TRUE)
## Warning in trace_terme_bivar(ajustement = ajust_inter_2, nom_terme = "Sexe:Age", : Utilisation des données de ajustement$data

Nous ne sommes certes pas confrontés à une prolifération de termes (ce qui peut être le cas lorsque l’on considère de nombreux termes d’interaction, ou des variables catégorielles comportant un nombre élevé de modalités). Néanmoins, le tracé ci-dessus suggère que l’on pourrait, pour ce qui concerne le terme d’interaction marginale, fusionner les deux premières classes d’âge 18-20 et 21-23, tout en laissant telles quelles les modalités des variables Sexe et Age pour l’estimation des effets principaux. On illustre maintenant l’une des manières de mener à bien une telle opération, en utilisant des fonctions d’encodage appropriées.

On commence par créer une fonction fus_Age permettant de transformer la variable Age en appliquant la fusion souhaitée.

fus_Age <- function(Age) {
  forcats::fct_collapse(.f = Age,
                        `18-23` = c("18-20", "21-23"),
                        `24-33` = "24-33",
                        `34-53` = "34-53",
                        `53-70` = "53-70",
                        `>70` = ">70")
}

On ré-ajuste ensuite le modèle, en utilisant la fonction inter_marginale.

# Ajustement avec interaction marginale et fusion
ajust_inter_3 <- glm(NbSin ~ Sexe + Age + inter_marginale(fus_Age(Age), Sexe) + offset(log(Exposition)),
                     family = poisson(link = "log"),
                     data = donnees)
summary(ajust_inter_3)
## 
## Call:
## glm(formula = NbSin ~ Sexe + Age + inter_marginale(fus_Age(Age), 
##     Sexe) + offset(log(Exposition)), family = poisson(link = "log"), 
##     data = donnees)
## 
## Coefficients:
##                                            Estimate Std. Error z value Pr(>|z|)
## (Intercept)                                -2.36935    0.01434 -165.26   <2e-16
## SexeH                                       0.89826    0.01371   65.52   <2e-16
## Age21-23                                   -0.15408    0.01385  -11.13   <2e-16
## Age24-33                                   -0.20915    0.01889  -11.07   <2e-16
## Age34-53                                   -0.41656    0.01980  -21.04   <2e-16
## Age53-70                                   -0.41172    0.02231  -18.45   <2e-16
## Age>70                                     -0.65481    0.02953  -22.17   <2e-16
## inter_marginale(fus_Age(Age), Sexe)24-33.H -0.65968    0.02257  -29.23   <2e-16
## inter_marginale(fus_Age(Age), Sexe)34-53.H -0.84506    0.02469  -34.23   <2e-16
## inter_marginale(fus_Age(Age), Sexe)53-70.H -0.86538    0.02836  -30.52   <2e-16
## inter_marginale(fus_Age(Age), Sexe)>70.H   -0.92764    0.03918  -23.67   <2e-16
##                                               
## (Intercept)                                ***
## SexeH                                      ***
## Age21-23                                   ***
## Age24-33                                   ***
## Age34-53                                   ***
## Age53-70                                   ***
## Age>70                                     ***
## inter_marginale(fus_Age(Age), Sexe)24-33.H ***
## inter_marginale(fus_Age(Age), Sexe)34-53.H ***
## inter_marginale(fus_Age(Age), Sexe)53-70.H ***
## inter_marginale(fus_Age(Age), Sexe)>70.H   ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance: 11991.2065  on 11  degrees of freedom
## Residual deviance:     0.0246  on  1  degrees of freedom
## AIC: 143.55
## 
## Number of Fisher Scoring iterations: 3

Et l’on effectue de nouveau les tracés précédents.

trace_terme_univar(ajustement = ajust_inter_3,
                   nom_terme = "Sexe",
                   nom_variable = "Sexe",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_3, nom_terme = "Sexe", : Utilisation des données de ajustement$data

trace_terme_univar(ajustement = ajust_inter_2,
                   nom_terme = "Age",
                   nom_variable = "Age",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_2, nom_terme = "Age", : Utilisation des données de ajustement$data

trace_terme_bivar(ajustement=ajust_inter_3,
                  nom_terme = "inter_marginale(fus_Age(Age), Sexe)",
                  nom_variable_2 = "Sexe",
                  nom_variable_1 = "Age",
                  trace_exposition = TRUE,
                  nom_exposition = "Exposition",
                  trace_int_conf = TRUE)
## Warning in trace_terme_bivar(ajustement = ajust_inter_3, nom_terme = "inter_marginale(fus_Age(Age), Sexe)", : Utilisation des données de ajustement$data

La décision d’inclure ou non des termes d’interaction dans un modèle peut, par exemple, faire l’objet de tests statistiques, ou être guidée par d’autres approches de comparaison de modèles.

Ci-dessous, on illustre simplement l’utilisation du test du rapport de vraisemblance dans ce contexte, praticable ici car les modèles que l’on va comparer sont emboîtés.

On commence par comparer le modèle avec et sans terme d’interaction, avec (sans surprise, vu les tracés précédents) un test qui penche très nettement en faveur de l’inclusion du terme d’interaction .

# Test LRT pour comparer le modèle avec et sans interaction
ajust_sans_inter <- glm(NbSin ~ Sexe + Age + offset(log(Exposition)),
                        family = poisson(link = "log"),
                        data = donnees)
anova(ajust_sans_inter, ajust_inter_2, test = "LRT")

On peut également comparer les modèles ajustés avec et sans fusion des modalités de Age dans le terme d’interaction marginale. Sans surprise, le test conduit à retenir la fusion.

# Test LRT pour comparer le modèle avec et sans interaction
anova(ajust_inter_3, ajust_inter_2, test = "LRT")

1.3 Un cas sans interaction

Afin de bien comprendre la différence avec ce qui précède, on travaille maintenant sur un jeu de données simulées selon un modèle additif (sans interaction). Par conséquent, l’inclusion de termes d’interaction est ici superflue, et il s’agit de voir comment ceci se reflète sur les modèles ajustés, du point de vue des tracés obtenus.

# Pour comparer : on recommence sur autre jeu de données simulées à l'aide d'un modèle additif (sans interaction)
load(url("https://irma.math.unistra.fr/~jberard/donnees_glm_sim_inter_bis")) 

Avec un ajustement utilisant une interaction “complète”, on constate le parallélisme entre les deux tracés, qui reflète l’absence d’interaction.

ajust_inter_1_bis <- glm(NbSin ~ interaction(Sexe, Age) + offset(log(Exposition)),
                         family = poisson(link = "log"),
                         data = donnees)
trace_terme_bivar(ajustement = ajust_inter_1_bis,
                  nom_terme = "interaction(Sexe, Age)",
                  nom_variable_2 = "Sexe",
                  nom_variable_1 = "Age",
                  trace_exposition = TRUE,
                  nom_exposition = "Exposition",
                  trace_int_conf = TRUE)
## Warning in trace_terme_bivar(ajustement = ajust_inter_1_bis, nom_terme = "interaction(Sexe, Age)", : Utilisation des données de ajustement$data

L’ajustement utilisant une interaction marginale permet de mettre en évidence de manière claire le caractère superflu du terme supplémentaire traduisant une possible interaction.

ajust_inter_2_bis <- glm(NbSin ~ Sexe + Age + Sexe:Age + offset(log(Exposition)),
                         family = poisson(link = "log"),
                         data = donnees)
trace_terme_univar(ajustement = ajust_inter_2_bis,
                   nom_terme = "Sexe",
                   nom_variable = "Sexe",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_2_bis, nom_terme = "Sexe", : Utilisation des données de ajustement$data

trace_terme_univar(ajustement = ajust_inter_2_bis,
                   nom_terme = "Age",
                   nom_variable = "Age",
                   trace_exposition = TRUE,
                   nom_exposition = "Exposition",
                   trace_int_conf = TRUE)
## Warning in trace_terme_univar(ajustement = ajust_inter_2_bis, nom_terme = "Age", : Utilisation des données de ajustement$data

trace_terme_bivar(ajustement = ajust_inter_2_bis,
                  nom_terme = "Sexe:Age",
                  nom_variable_2 = "Sexe",
                  nom_variable_1 = "Age",
                  trace_exposition = TRUE,
                  nom_exposition = "Exposition",
                  trace_int_conf = TRUE,
                  facteur_dessous = 20,
                  facteur_dessus = 20)
## Warning in trace_terme_bivar(ajustement = ajust_inter_2_bis, nom_terme = "Sexe:Age", : Utilisation des données de ajustement$data

2 Interactions quantitative-quantitative et quantitative-catégorielle

2.1 Récupération des données

On travaille maintenant avec un jeu de données d’assurance, retraité du paquet CASdatasets.

load(url("https://irma.math.unistra.fr/~jberard/swmotorcycle_recat")) # Données retraitées de CASdatasets
str(donnees)
## 'data.frame':    62474 obs. of  9 variables:
##  $ ClaimAmount: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ ClaimNb    : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Exposure   : num  0.175 0.455 0.173 0.181 0.542 ...
##  $ Area       : Factor w/ 7 levels "1","2","3","4",..: 1 3 4 2 3 4 2 4 4 2 ...
##  $ RiskClass  : Factor w/ 7 levels "EV[0,5]","EV[25,Inf]",..: 3 7 1 1 7 3 7 6 3 7 ...
##  $ OwnerAge   : int  0 5 5 6 9 9 10 10 10 11 ...
##  $ Gender     : Factor w/ 2 levels "Female","Male": 2 1 1 1 1 2 2 2 2 1 ...
##  $ VehAge     : int  12 18 25 26 8 20 16 17 21 13 ...
##  $ BonusClass : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...

2.2 Ajustements

On se placera ci-dessous dans le cadre des modèles additifs généralisés, et l’on utilisera le paquet mgcv pour effectuer les ajustements.

library(mgcv)
## Loading required package: nlme
## This is mgcv 1.9-1. For overview type 'help("mgcv-package")'.

Pour commencer, on illustre l’utilisation d’une interaction complète des variables VehAge et OwnerAge, toutes deux quantitatives, en utilisant te().

# Modèle avec interaction complète de VehAge et OwnerAge : te()
ajustement_1 <- gam(ClaimNb ~
                    Area +
                    RiskClass +
                    BonusClass +
                    te(VehAge, OwnerAge) +
                    offset(log(Exposure)),
                    family = poisson(link = "log"),
                    data = donnees,
                    control = list(keepData = TRUE))
summary(ajustement_1)
## 
## Family: poisson 
## Link function: log 
## 
## Formula:
## ClaimNb ~ Area + RiskClass + BonusClass + te(VehAge, OwnerAge) + 
##     offset(log(Exposure))
## 
## Parametric coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)         -4.07164    0.17788 -22.890  < 2e-16 ***
## Area2               -0.52680    0.10832  -4.863 1.15e-06 ***
## Area3               -1.02440    0.11862  -8.636  < 2e-16 ***
## Area4               -1.46714    0.10590 -13.854  < 2e-16 ***
## Area5               -1.69617    0.34221  -4.957 7.18e-07 ***
## Area6               -1.35841    0.24862  -5.464 4.66e-08 ***
## Area7               -1.83741    1.00312  -1.832 0.066995 .  
## RiskClassEV[25,Inf]  0.21290    0.43940   0.485 0.628019    
## RiskClassEV[13,15]  -0.22573    0.18608  -1.213 0.225101    
## RiskClassEV[16,19]   0.19589    0.17796   1.101 0.271000    
## RiskClassEV[20,24]   0.66827    0.17739   3.767 0.000165 ***
## RiskClassEV[6,8]     0.19796    0.20112   0.984 0.324973    
## RiskClassEV[9,12]   -0.35405    0.17318  -2.044 0.040915 *  
## BonusClass2          0.16613    0.11758   1.413 0.157671    
## BonusClass3          0.18215    0.09966   1.828 0.067584 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##                       edf Ref.df Chi.sq p-value    
## te(VehAge,OwnerAge) 8.578  9.897    537  <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## R-sq.(adj) =  0.0119   Deviance explained = 13.9%
## UBRE = -0.90763  Scale est. = 1         n = 62474

On effectue maintenant un tracé de l’effet correspondant (consulter documentation de la fonction vis.gam pour davantage d’explications).

vis.gam(ajustement_1, view = c("VehAge", "OwnerAge"), plot.type = "contour", contour.col = "black")

vis.gam(ajustement_1, view = c("VehAge", "OwnerAge"), color = "heat", border = NA, theta = 120, phi = 30, ticktype = "detailed")

On illustre maintenant l’utilisation d’une interaction marginale des variables VehAge et OwnerAge en utilisant ti(), les effets principaux étant produits par s() pour chacune des deux variables.

# Modèle avec interaction marginale de VehAge et OwnerAge : ti()
ajustement_2 <- gam(ClaimNb ~
                    Area +
                    RiskClass +
                    BonusClass +
                    s(VehAge) + 
                    s(OwnerAge) + 
                    ti(VehAge, OwnerAge) +
                    offset(log(Exposure)),
                    family = poisson(link = "log"),
                    data = donnees,
                    control = list(keepData = TRUE))
summary(ajustement_2)
## 
## Family: poisson 
## Link function: log 
## 
## Formula:
## ClaimNb ~ Area + RiskClass + BonusClass + s(VehAge) + s(OwnerAge) + 
##     ti(VehAge, OwnerAge) + offset(log(Exposure))
## 
## Parametric coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)         -4.01282    0.17773 -22.579  < 2e-16 ***
## Area2               -0.53285    0.10836  -4.918 8.76e-07 ***
## Area3               -1.03284    0.11870  -8.701  < 2e-16 ***
## Area4               -1.47008    0.10600 -13.868  < 2e-16 ***
## Area5               -1.70827    0.34229  -4.991 6.02e-07 ***
## Area6               -1.36555    0.24873  -5.490 4.02e-08 ***
## Area7               -1.83976    1.00314  -1.834 0.066654 .  
## RiskClassEV[25,Inf]  0.16654    0.44016   0.378 0.705161    
## RiskClassEV[13,15]  -0.28346    0.18807  -1.507 0.131759    
## RiskClassEV[16,19]   0.14135    0.18014   0.785 0.432626    
## RiskClassEV[20,24]   0.61585    0.18032   3.415 0.000637 ***
## RiskClassEV[6,8]     0.16648    0.20210   0.824 0.410098    
## RiskClassEV[9,12]   -0.40313    0.17483  -2.306 0.021120 *  
## BonusClass2          0.14879    0.11761   1.265 0.205823    
## BonusClass3          0.18668    0.09917   1.882 0.059784 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##                       edf Ref.df  Chi.sq p-value    
## s(VehAge)           2.384  2.944 137.781  <2e-16 ***
## s(OwnerAge)         5.767  6.444 202.069  <2e-16 ***
## ti(VehAge,OwnerAge) 1.828  2.306   2.068   0.433    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## R-sq.(adj) =  0.0121   Deviance explained =   14%
## UBRE = -0.90769  Scale est. = 1         n = 62474

On illustre maintenant une interaction entre la variable quantitative OwnerAge et la variable catégorielle BonusClass, en spécifiant dans la formule que le terme lisse s(BonusClass) doit être modulé selon la valeur de BonusClass.

# Modèle avec interaction marginale de OwnerAge et BonusClass
ajustement_3 <- gam(ClaimNb ~
                    Area +
                    RiskClass +
                    BonusClass +
                    s(VehAge) +
                    s(OwnerAge) + 
                    s(OwnerAge, by = BonusClass) +
                    offset(log(Exposure)),
                    family = poisson(link = "log"),
                    data = donnees,
                    control = list(keepData = TRUE))
summary(ajustement_3)
## 
## Family: poisson 
## Link function: log 
## 
## Formula:
## ClaimNb ~ Area + RiskClass + BonusClass + s(VehAge) + s(OwnerAge) + 
##     s(OwnerAge, by = BonusClass) + offset(log(Exposure))
## 
## Parametric coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)          -4.1591     0.1918 -21.682  < 2e-16 ***
## Area2                -0.5394     0.1084  -4.977 6.47e-07 ***
## Area3                -1.0325     0.1187  -8.698  < 2e-16 ***
## Area4                -1.4692     0.1061 -13.853  < 2e-16 ***
## Area5                -1.7086     0.3423  -4.991 5.99e-07 ***
## Area6                -1.3531     0.2487  -5.441 5.31e-08 ***
## Area7                -1.8556     1.0033  -1.849 0.064399 .  
## RiskClassEV[25,Inf]   0.2006     0.4399   0.456 0.648391    
## RiskClassEV[13,15]   -0.2771     0.1877  -1.476 0.139963    
## RiskClassEV[16,19]    0.1515     0.1796   0.843 0.398976    
## RiskClassEV[20,24]    0.6247     0.1797   3.477 0.000507 ***
## RiskClassEV[6,8]      0.1692     0.2018   0.839 0.401639    
## RiskClassEV[9,12]    -0.3988     0.1746  -2.284 0.022384 *  
## BonusClass2           0.3092     0.1598   1.935 0.052966 .  
## BonusClass3           0.3442     0.1274   2.702 0.006899 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##                              edf   Ref.df  Chi.sq p-value    
## s(VehAge)               2.425158 2.990943 163.935  <2e-16 ***
## s(OwnerAge)             4.471912 5.252943 129.002  <2e-16 ***
## s(OwnerAge):BonusClass1 0.001533 0.002933   0.000  0.9985    
## s(OwnerAge):BonusClass2 1.001356 1.002658   2.014  0.1564    
## s(OwnerAge):BonusClass3 5.535916 6.187882  12.704  0.0601 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Rank: 59/60
## R-sq.(adj) =  0.0121   Deviance explained = 14.2%
## UBRE = -0.90774  Scale est. = 1         n = 62474

Variante de ce qui précède, en imposant une pénalisation égale pour les différentes modalités de BonusClass.

# Modèle avec interaction marginale de OwnerAge et BonusClass 
# et pénalisation égale pour les différentes modalités de BonusClass
ajustement_4 <- gam(ClaimNb ~
                    Area +
                    RiskClass +
                    BonusClass +
                    s(VehAge) +
                    s(OwnerAge) + 
                    s(OwnerAge, by = BonusClass, id = "inter") + 
                    offset(log(Exposure)),
                    family = poisson(link = "log"),
                    data = donnees,
                    control = list(keepData = TRUE))
summary(ajustement_4)
## 
## Family: poisson 
## Link function: log 
## 
## Formula:
## ClaimNb ~ Area + RiskClass + BonusClass + s(VehAge) + s(OwnerAge) + 
##     s(OwnerAge, by = BonusClass, id = "inter") + offset(log(Exposure))
## 
## Parametric coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)          -4.1406     0.1904 -21.744  < 2e-16 ***
## Area2                -0.5391     0.1084  -4.975 6.53e-07 ***
## Area3                -1.0330     0.1187  -8.702  < 2e-16 ***
## Area4                -1.4702     0.1060 -13.864  < 2e-16 ***
## Area5                -1.7156     0.3423  -5.012 5.39e-07 ***
## Area6                -1.3612     0.2487  -5.473 4.42e-08 ***
## Area7                -1.8304     1.0031  -1.825 0.068041 .  
## RiskClassEV[25,Inf]   0.1782     0.4401   0.405 0.685655    
## RiskClassEV[13,15]   -0.2863     0.1882  -1.521 0.128175    
## RiskClassEV[16,19]    0.1353     0.1802   0.751 0.452856    
## RiskClassEV[20,24]    0.6114     0.1803   3.390 0.000698 ***
## RiskClassEV[6,8]      0.1603     0.2020   0.793 0.427511    
## RiskClassEV[9,12]    -0.4078     0.1750  -2.331 0.019755 *  
## BonusClass2           0.3067     0.1580   1.941 0.052230 .  
## BonusClass3           0.3262     0.1223   2.668 0.007628 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##                             edf  Ref.df  Chi.sq p-value    
## s(VehAge)               2.43272 2.99990 165.162  <2e-16 ***
## s(OwnerAge)             5.81494 6.48508 128.943  <2e-16 ***
## s(OwnerAge):BonusClass1 0.02185 0.04269   0.000   0.986    
## s(OwnerAge):BonusClass2 1.01835 1.03629   1.733   0.194    
## s(OwnerAge):BonusClass3 1.02663 1.05182   3.436   0.070 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Rank: 59/60
## R-sq.(adj) =  0.0123   Deviance explained =   14%
## UBRE = -0.90772  Scale est. = 1         n = 62474