Analyse descriptive des variables catégorielles

Il y quelques temps, j’ai publié un article sur l’analyse descriptive des variables numériques. Pour ne pas laisser en reste les variables descriptives, je vais vous montrer, dans ce post, quelques fonctions R qui permettent de réaliser facilement une analyse descriptive de ce type de variable. Plus précisément, je vais vous parler de fonctions qui permettent de:
  1. manipuler très simplement les modalités (ou levels) de ces variables,
  2. calculer facilement les pourcentages d’observations des différentes modalités, ainsi que leurs intervalles de confiance,
  3. calculer les pourcentages d’observations, et leurs intervalles de confiance, lorsque deux variables catégorielles sont combinées.
Pour illustrer cet article, je vais utiliser le jeu de données Melanoma, du package MASS. Ce jeu de données n’est pas des plus drôle, puisque il concerne des patients atteints de Mélanome malin, mais il a l’avantage de comporter 3 variables catégorielles (qui ont 2 modalités pour deux d’entre elles, et 3 modalités pour la dernière):
  1. sex :
– 1 pour les hommes, – 0 pour les femmes. 2. ulcer : – 1 présent, – 2 absent. 3. status : – 1 si le patient est décédé des suites du Melanome, – 2 s’il est vivant, – 3 s’il est décédé d’une auter cause).
library(MASS)
head(Melanoma)

    ##   time status sex age year thickness ulcer
    ## 1   10      3   1  76 1972      6.76     1
    ## 2   30      3   1  56 1968      0.65     0
    ## 3   35      2   1  41 1977      1.34     0
    ## 4   99      3   0  71 1968      2.90     0
    ## 5  185      1   1  52 1965     12.08     1
    ## 6  204      1   1  28 1971      4.84     1

1. Manipulation des modalités des variables catégorielles

1.1 La fonction as.factor

Dans R, les variables catégorielles sont des objets de type factor.Or, si on affiche la structure des données Melanoma avec la fonction str, on s’aperçoit que les variables status, sex et ulcer sont considérées comme des variables numériques de type entier (int).
 str(Melanoma)

    ## 'data.frame':    205 obs. of  7 variables:
    ##  $ time     : int  10 30 35 99 185 204 210 232 232 279 ...
    ##  $ status   : int  3 3 2 3 1 1 1 3 1 1 ...
    ##  $ sex      : int  1 1 1 0 1 1 1 0 1 0 ...
    ##  $ age      : int  76 56 41 71 52 28 77 60 49 68 ...
    ##  $ year     : int  1972 1968 1977 1968 1965 1971 1972 1974 1968 1971 ...
    ##  $ thickness: num  6.76 0.65 1.34 2.9 12.08 ...
    ##  $ ulcer    : int  1 0 0 0 1 1 1 1 1 1 ...
Nous allons donc commencer par les passer en variables catégorielles (factor dans R) à l’aide de la fonction as.factor.
 Melanoma$status <- as.factor(Melanoma$status)
    Melanoma$sex <- as.factor(Melanoma$sex)
    Melanoma$ulcer <- as.factor(Melanoma$ulcer)

    str(Melanoma)

    ## 'data.frame':    205 obs. of  7 variables:
    ##  $ time     : int  10 30 35 99 185 204 210 232 232 279 ...
    ##  $ status   : Factor w/ 3 levels "1","2","3": 3 3 2 3 1 1 1 3 1 1 ...
    ##  $ sex      : Factor w/ 2 levels "0","1": 2 2 2 1 2 2 2 1 2 1 ...
    ##  $ age      : int  76 56 41 71 52 28 77 60 49 68 ...
    ##  $ year     : int  1972 1968 1977 1968 1965 1971 1972 1974 1968 1971 ...
    ##  $ thickness: num  6.76 0.65 1.34 2.9 12.08 ...
    ##  $ ulcer    : Factor w/ 2 levels "0","1": 2 1 1 1 2 2 2 2 2 2 ...
Les 3 variables sont à présent considérées comme des facteurs.

1.2. La fonction levels

1.2.1 Pour afficher les modalités

Lorsqu’on ne connait pas à l’avance les modalités des variables catégorielles d’un jeu de données, il peut être utile de les afficher. Ces modalités (ou levels) sont affichées dans la sortie de la fonctionstr, mais il est parfois plus pratique d’utiliser la fonction levels, qui n’affichera que cette information.
levels(Melanoma$status)

    ## [1] "1" "2" "3"

1.2.2 Pour changer les étiquettes des modalités

On peut vouloir changer les étiquettes des modalités afin qu’elles soient plus parlantes. Par exemple, changer les codes 1, 2 et 3 de la variable status en “dcd_Melanome”, “vivant”, “dcd_autres”. Pour cela, on utilise encore la fonction levels.
 table(Melanoma$status)

    ## 
    ##   1   2   3 
    ##  57 134  14
La fonction table employée permet simplement d’accéder aux nombres d’observations par catégories, et de montrer que seules les étiquettes vont être changées, puisque les nombre d’observations sont identiques.
Melanoma2 <- Melanoma

    levels(Melanoma2$status)[c(1,2,3)] <- c("dcd_Melanome", "vivant", "dcd_autres")
    table(Melanoma2$status)

    ## 
    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           14

1.2.3 Pour regrouper des modalités

On peut aussi avoir besoin de regrouper certains niveaux entre eux. On pourrait, par exemple, avoir besoin de regrouper les modalités “dcd_Melanome” et “dcd_autres”, pour former un seul niveau “dcd”. Là encore, on utilise la fonction levels.
levels(Melanoma2$status)[c(1,3)] <- c("dcd")
    table(Melanoma2$status)

    ## 
    ##    dcd vivant 
    ##     71    134
Les indices 1 et 3 correspondent aux rangs des modalités que l’on souhaite regrouper.

1.3 La fonction “ordered”

On peut aussi avoir besoin de changer l’ordre des modalités. C’est souvent le cas dans les représentations graphiques, par exemple lorsqu’on souhaite faire apparaître une certaine modalité en première position. Initialement l’ordre des modalités est celui de l’ordre alphabétique. La fonction ordered permet de le changer:
Melanoma2$status <- ordered(Melanoma2$status, levels=c("vivant", "dcd"))

    table(Melanoma2$status)

    ## 
    ## vivant    dcd 
    ##    134     71

2. Calculer les pourcentages et les intervalles de confiance des différentes modalités

2.1 Les fonctions table ou xtabs et sum pour obtenir le nombre d’observations

Avant de calculer les pourcentages, il est souvent utile de connaitre le nombre d’observations par modalité. Les fonctionstable du package base et xtabs du package stats permettent d’obtenir ces informations. Enfin, la fonction sum permet d’obtenir le nombre total d’observations.
Melanoma2 <- Melanoma
    levels(Melanoma2$status)[c(1,2,3)] <- c("dcd_Melanome", "vivant", "dcd_autres")

    table(Melanoma2$status, useNA="ifany")

    ## 
    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           14

    xtabs(~Melanoma2$status, addNA = TRUE)

    ## Melanoma2$status
    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           14

    sum(table(Melanoma2$status))

    ## [1] 205
Il est important de noter que, par défaut, les fonctions table et xtabs ne renvoient pas le nombre de données manquantes. Pour cela il est nécessaire d’employer spécifiquement les arguments useNA="ifany"dans la fonction table, et addNA = TRUE dans la fonction xtabs :
 # je crée un nouveau jeu de données en copiant Melanoma2
    Melanoma3 <- Melanoma2

    # je créé des données manquantes sur la deuxième ligne
    Melanoma3[2,] <- NA

    table(Melanoma3$status)

    ## 
    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           13

    table(Melanoma3$status,useNA="ifany" )

    ## 
    ## dcd_Melanome       vivant   dcd_autres         <NA> 
    ##           57          134           13            1

    xtabs(~Melanoma3$status)

    ## Melanoma3$status
    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           13

    xtabs(~Melanoma3$status,addNA=TRUE )  

    ## Melanoma3$status
    ## dcd_Melanome       vivant   dcd_autres         <NA> 
    ##           57          134           13            1

2.2 La fonction prop.table pour calculer la fréquence de chaque modalité

 TC <- table(Melanoma2$status)
    prop.table(TC)

    ## 
    ## dcd_Melanome       vivant   dcd_autres 
    ##   0.27804878   0.65365854   0.06829268

    round(prop.table(TC),2)

    ## 
    ## dcd_Melanome       vivant   dcd_autres 
    ##         0.28         0.65         0.07
Il suffit alors de multiplier par 100 pour obtenir les pourcentages.

2.3 La fonction describe du package “Hmisc”

Cette fonction est très complète puisqu’elle permet d’afficher :
  • le nombre total d’observations
  • le nombre de données manquantes
  • le nombre de modalités
  • le nombre d’observations pour chaque modalité
  • le pourcentage d’observations pour chaque modalité.
library(Hmisc)
    describe(Melanoma2["status"])

    ## Melanoma2["status"] 
    ## 
    ##  1  Variables      205  Observations
    ## ---------------------------------------------------------------------------
    ## status 
    ##        n  missing distinct 
    ##      205        0        3 
    ##                                                  
    ## Value      dcd_Melanome       vivant   dcd_autres
    ## Frequency            57          134           14
    ## Proportion        0.278        0.654        0.068
    ## ---------------------------------------------------------------------------
La fonction describe peut prendre en argument plusieurs variables catégorielles :
describe(Melanoma2[c("status","sex","ulcer")])

    ## Melanoma2[c("status", "sex", "ulcer")] 
    ## 
    ##  3  Variables      205  Observations
    ## ---------------------------------------------------------------------------
    ## status 
    ##        n  missing distinct 
    ##      205        0        3 
    ##                                                  
    ## Value      dcd_Melanome       vivant   dcd_autres
    ## Frequency            57          134           14
    ## Proportion        0.278        0.654        0.068
    ## ---------------------------------------------------------------------------
    ## sex 
    ##        n  missing distinct 
    ##      205        0        2 
    ##                       
    ## Value          0     1
    ## Frequency    126    79
    ## Proportion 0.615 0.385
    ## ---------------------------------------------------------------------------
    ## ulcer 
    ##        n  missing distinct 
    ##      205        0        2 
    ##                       
    ## Value          0     1
    ## Frequency    115    90
    ## Proportion 0.561 0.439
    ## ---------------------------------------------------------------------------

2.4 La fonction prop.test pour obtenir l’intervalle de confiance

L’intervalle de confiance est estimé selon une distribution binomiale.Il peut être estimé en utilisant prop.test(obs, nb_tot_obs)$conf.int
 prop.test(57,205)$conf.int

    ## [1] 0.2189967 0.3455870
    ## attr(,"conf.level")
    ## [1] 0.95

    prop.test(134,205)$conf.int

    ## [1] 0.5837414 0.7177133
    ## attr(,"conf.level")
    ## [1] 0.95

    prop.test(14,205)$conf.int

    ## [1] 0.03926595 0.11428401
    ## attr(,"conf.level")
    ## [1] 0.95
Le niveau de confiance peut être modifié par l’argument conf.level de la fonction prop.test.

2.5 La fonction binom.confint pour calculer les intervalles de confiance de plusieurs pourcentages

Bien qu’elle soit un tout petit peu plus difficile à utiliser, la fonction binom.confint du package binom est particulièrement utile pour calculer les intervalles de confiance des fréquences de chaque modalité d’une variable catégorielle.
 # on récupère les nombres d'observation par modalité
    nb <- as.vector(table(Melanoma2$status))
    # on créé un vecteur contenant 3x le nombre totale d'observations car on a 3 modalité
    nbT <- rep(sum(nb, length(nb)))

    library("binom")
    df <- binom.confint(nb, nbT, conf.level=0.95, methods="prop.test")
    rownames(df) <- levels(Melanoma2$status)
    df

    ##                 method   x   n       mean      lower     upper
    ## dcd_Melanome prop.test  57 208 0.27403846 0.21573508 0.3408582
    ## vivant       prop.test 134 208 0.64423077 0.57463875 0.7084006
    ## dcd_autres   prop.test  14 208 0.06730769 0.03869379 0.1126836
Les intervalles de confiance peuvent être estimés selon 8 méthodes différentes. Pour plus d’infos, consultez la page d’aide :?binom.confint

3. Calculer les pourcentages et les intervalles de confiance des combinaisons de deux variables catégorielles

Il s’agit par exemple d’étudier la répartition de la variable status en fonction de la variable sex.

3.1 Les fonctions table ou xtabs pour créer une table de contingence

Les tables de contingence sont simplement des tableaux à double entrées avec le nombre d’observations correspondant à chaque croisement de modalités. Comme précédemment, il peut être utile, dans un premier temps, d’accéder à cette information.
 # on renomme les levels de la variable sex
    levels(Melanoma2$sex)[c(1,2)] <- c("F", "M")
    table(Melanoma2$status, Melanoma2$sex)

    ##               
    ##                 F  M
    ##   dcd_Melanome 28 29
    ##   vivant       91 43
    ##   dcd_autres    7  7

3.2 Les fonctions rowSums et colSums

La fonction rowSums permet de calculer la somme des observations par ligne.
 TC <- table(Melanoma2$status, Melanoma2$sex)
    rowSums(TC)

    ## dcd_Melanome       vivant   dcd_autres 
    ##           57          134           14
Alors que a fonction colSums permet de le faire par colonne.
    TC <- table(Melanoma2$status, Melanoma2$sex)
    colSums(TC)

    ##   F   M 
    ## 126  79

3.3 La fonction prop.table pour calculer les pourceantges globaux, par ligne , ou par colonne

La fonction prop.table prend en argument une table de contingence. Par défaut, elle calcule les fréquences globales (la somme des fréquences de toutes les modalités = 1). Employée avec l’argument 1, la fonction calcule les fréquences par ligne (la somme des fréquences de chaque lignes =1). Enfin, avec l’argument 2, la fonction les calcule par colonne (la somme des fréquences de chaque colonne = 1).
options(digits = 2)

    TC <- with(Melanoma2, table(status, sex))
    prop.table(TC)

    ##               sex
    ## status             F     M
    ##   dcd_Melanome 0.137 0.141
    ##   vivant       0.444 0.210
    ##   dcd_autres   0.034 0.034

    prop.table(TC,1)

    ##               sex
    ## status            F    M
    ##   dcd_Melanome 0.49 0.51
    ##   vivant       0.68 0.32
    ##   dcd_autres   0.50 0.50

    prop.table(TC,2)

    ##               sex
    ## status             F     M
    ##   dcd_Melanome 0.222 0.367
    ##   vivant       0.722 0.544
    ##   dcd_autres   0.056 0.089

3.4 La fonction binom.confint pour calculer les intervalles de confiance

On peut, par exemple, souhaiter calculer les intervalles de confiance des pourcentages d’hommes et de femmes pour chacune des modalités de la variable status. Bien que cela demande quelques manipulations la fonction binom.confint permet d’obtenir assez facilement ces intervalles.
options(digits=2)
    TC <- with(Melanoma2, table(status, sex))

    # affichage des fréquences pour lesquelles on veut calculer un IC
    prop.table(TC,1) 

    ##               sex
    ## status            F    M
    ##   dcd_Melanome 0.49 0.51
    ##   vivant       0.68 0.32
    ##   dcd_autres   0.50 0.50

    # on récupère le nb d'observations pour les femmes pour tous les status
    nb.F <- as.vector(TC[,1]) 

    # idem pour les hommes
    nb.M <- as.vector(TC[,2])

    # on récupère le nombre total d'observations pour chaque status
    nbT <- rowSums(TC)

    # on calcule les IC pour les fréquences de femmes
    df.F <- binom.confint(nb.F, nbT, conf.level=0.95, methods="prop.test")
    rownames(df.F) <- paste("F", rownames(TC), sep="__")

    # on affiche le tableau obtenu pour les femmes
    df.F

    ##                    method  x   n mean lower upper
    ## F__dcd_Melanome prop.test 28  57 0.49  0.36  0.63
    ## F__vivant       prop.test 91 134 0.68  0.59  0.76
    ## F__dcd_autres   prop.test  7  14 0.50  0.27  0.73

    # idem pour les hommes
    df.M <- binom.confint(nb.M, nbT, conf.level=0.95, methods="prop.test")
    rownames(df.M) <- paste("M", rownames(TC), sep="__")
    df.M

    ##                    method  x   n mean lower upper
    ## M__dcd_Melanome prop.test 29  57 0.51  0.37  0.64
    ## M__vivant       prop.test 43 134 0.32  0.24  0.41
    ## M__dcd_autres   prop.test  7  14 0.50  0.27  0.73

    # on colle les lignes
    df<-rbind(df.F, df.M)
    # on affiche le tableau final
    df

    ##                    method  x   n mean lower upper
    ## F__dcd_Melanome prop.test 28  57 0.49  0.36  0.63
    ## F__vivant       prop.test 91 134 0.68  0.59  0.76
    ## F__dcd_autres   prop.test  7  14 0.50  0.27  0.73
    ## M__dcd_Melanome prop.test 29  57 0.51  0.37  0.64
    ## M__vivant       prop.test 43 134 0.32  0.24  0.41
    ## M__dcd_autres   prop.test  7  14 0.50  0.27  0.73
Relativement pratique, non ? J’espère que cet article vous sera utile et qu’il vous aidera à être plus à l’aise et plus efficace pour décrire vos variables catégorielles. S’il vous a plu, n’hésitez pas à le partager ! Dans un prochain post, je vous parlerai des représentations graphiques que l’on peut employer pour visualiser les variables catégorielles. En attendant, si vous utilisez d’autres fonctions dont je n’ai pas parlé ici, indiquez les moi dans un commentaire. Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee 🙏 👉 Cliquez ici pour soutenir le blog Statistiques et Logiciel R   Crédits photos : ColiN00B

Retrouvez ici 3 de mes articles les plus consultés:

12 conseils pour organiser efficacement vos données dans un tableur Comment insérer des références bibliographiques dans un document Rmarkdown? Comment retrouver sous R une couleur employée avec Excel?

4 réponses

  1. Merci infiniment pour ce tutoriel très didactique en français !
    Je signale juste une petite faute de frappe qui m’a déconcerté un moment (si ça peut profiter à d’autres lecteurs…)
    Section 2.5, ligne 4 du code, une parenthèse a glissé :
    C’ est: nbT <- rep(sum(nb), length(nb))
    et non pas: nbT <- rep(sum(nb, length(nb)))
    Merci encore pour ce que vous faites.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *