Faire une table one ultra facilement

Réalisez une table one ultra facilement

Il y a quelque temps, j’ai publié un article pour vous montrer comment réaliser une table descriptive, dite Table 1, avec le package Table1. 

Mais plusieurs lecteurs (et lectrices 😉 ) m’ont écrit pour me dire qu’ils rencontraient des difficultés pour installer ce package, car il n’est pas sur CRAN. En effet, actuellement pour le moins, ce package doit être téléchargé à partir d’un répertoire Github. Et les restrictions informatiques des certaines organisations (facultés, entreprises, etc…) ne permettent pas toujours (ou plus difficilement) ce type de téléchargement.

Je vous propose donc une autre solution : utiliser le package tableone !

Ce package est téléchargeable sur CRAN, il permet de faire de belles tables one, et en plus les sorties sont facilement exportables en format csv !

Quoi demander de plus ?

De pouvoir choisir de présenter la moyenne et l’écart-type, ou la médiane et l’intervalle inter-quartile selon si les variables quantitatives suivent, ou  pas une distribution normale ?

Eh bien, il le fait aussi ! Si si ….. Je vous montre tout ça en pas à pas.

Table des matières

Les data utilisées

Nous allons employer les données cgd du package survival.  Les données proviennent d’un essai contrôlé par placebo sur l’interféron gamma dans la maladie granulotomique chronique (CGD).

install.packages(survival)
library(survival)
str(cgd)
## 'data.frame':    203 obs. of  16 variables:
##  $ id      : int  1 1 1 2 2 2 2 2 2 2 ...
##  $ center  : Factor w/ 13 levels "Harvard Medical Sch",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ random  : Date, format: "1989-06-07" "1989-06-07" ...
##  $ treat   : Factor w/ 2 levels "placebo","rIFN-g": 2 2 2 1 1 1 1 1 1 1 ...
##  $ sex     : Factor w/ 2 levels "male","female": 2 2 2 1 1 1 1 1 1 1 ...
##  $ age     : int  12 12 12 15 15 15 15 15 15 15 ...
##  $ height  : num  147 147 147 159 159 159 159 159 159 159 ...
##  $ weight  : num  62 62 62 47.5 47.5 47.5 47.5 47.5 47.5 47.5 ...
##  $ inherit : Factor w/ 2 levels "X-linked","autosomal": 2 2 2 2 2 2 2 2 2 2 ...
##  $ steroids: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ propylac: num  0 0 0 1 1 1 1 1 1 1 ...
##  $ hos.cat : Factor w/ 4 levels "US:NIH","US:other",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ tstart  : int  0 219 373 0 8 26 152 241 249 322 ...
##  $ enum    : int  1 2 3 1 2 3 4 5 6 7 ...
##  $ tstop   : int  219 373 414 8 26 152 241 249 322 350 ...
##  $ status  : int  1 1 0 1 1 1 1 1 1 1 ... 

Principe pour la création de la table one

Le principe est assez simple :

  • créer un subset de données avec les variables quantitatives et qualitatives à intégrer dans la table one.
  • employer la fonction CreateTableOne()
  • employer une fonction print() avec différents arguments pour modifier la table one créée :
    • Par exemple pour justement préciser quelles variables numériques ne sont pas distribuées normalement, et pour lesquelles nous souhaitons afficher une médiane et un intervalle interquartile, à la place d’une moyenne et d’un sd.
    • Ou encore pour préciser en cas de stratification ( deux bras de traitement par exemple), si nous souhaitons réaliser des tests de comparaison et afficher les p-values correspondantes.

Tutoriel

Création du subset

library(dplyr)

mydata <- cgd %>% 
    dplyr::select(treat :hos.cat)
    

str(mydata)
## 'data.frame':    203 obs. of  9 variables:
##  $ treat   : Factor w/ 2 levels "placebo","rIFN-g": 2 2 2 1 1 1 1 1 1 1 ...
##  $ sex     : Factor w/ 2 levels "male","female": 2 2 2 1 1 1 1 1 1 1 ...
##  $ age     : int  12 12 12 15 15 15 15 15 15 15 ...
##  $ height  : num  147 147 147 159 159 159 159 159 159 159 ...
##  $ weight  : num  62 62 62 47.5 47.5 47.5 47.5 47.5 47.5 47.5 ...
##  $ inherit : Factor w/ 2 levels "X-linked","autosomal": 2 2 2 2 2 2 2 2 2 2 ...
##  $ steroids: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ propylac: num  0 0 0 1 1 1 1 1 1 1 ...
##  $ hos.cat : Factor w/ 4 levels "US:NIH","US:other",..: 2 2 2 2 2 2 2 2 2 2 ... 

Nous allons passer en facteur les variables steroids et propylac et les recoder :

mydata$steroids <- factor(mydata$steroids) 
mydata$propylac <- factor(mydata$propylac) 

library(forcats)
mydata$steroids <- fct_recode(mydata$steroids,
                              no="0",
                              yes="1")

mydata$propylac <- fct_recode(mydata$propylac,
                              no="0",
                              yes="1") 

Créer une table one globale

install.packages("tableone")
library(tableone)
CreateTableOne(data=mydata)
##                          
##                           Overall       
##   n                          203        
##   treat = rIFN-g (%)          83 (40.9) 
##   sex = female (%)            35 (17.2) 
##   age (mean (SD))          13.70 (9.34) 
##   height (mean (SD))      138.12 (31.41)
##   weight (mean (SD))       39.34 (21.83)
##   inherit = autosomal (%)     72 (35.5) 
##   steroids = yes (%)           7 ( 3.4) 
##   propylac = yes (%)         172 (84.7) 
##   hos.cat (%)                           
##      US:NIH                   41 (20.2) 
##      US:other                108 (53.2) 
##      Europe:Amsterdam         28 (13.8) 
##      Europe:other             26 (12.8) 

Améliorer l'affichage de la table one globale

Lorsqu’une variable qualitative n’a que deux modalités (par exemple trt), seule la modalité de référence est spécifiée dans la table….

Ce n’est pas génial du tout !

Alors pour modifier cela nous devons :

  1. stocker la table dans un objet
  2. utiliser la fonction print(), avec l’argument showAllLevels = TRUE
table_globale <- CreateTableOne(data=mydata)
print(table_globale, showAllLevels = TRUE)
##                     
##                      level            Overall       
##   n                                      203        
##   treat (%)          placebo             120 (59.1) 
##                      rIFN-g               83 (40.9) 
##   sex (%)            male                168 (82.8) 
##                      female               35 (17.2) 
##   age (mean (SD))                      13.70 (9.34) 
##   height (mean (SD))                  138.12 (31.41)
##   weight (mean (SD))                   39.34 (21.83)
##   inherit (%)        X-linked            131 (64.5) 
##                      autosomal            72 (35.5) 
##   steroids (%)       no                  196 (96.6) 
##                      yes                   7 ( 3.4) 
##   propylac (%)       no                   31 (15.3) 
##                      yes                 172 (84.7) 
##   hos.cat (%)        US:NIH               41 (20.2) 
##                      US:other            108 (53.2) 
##                      Europe:Amsterdam     28 (13.8) 
##                      Europe:other         26 (12.8) 

C’est quand même vraiment mieux !

Choisir les paramètres des variables numériques

Ce qui est classique, c’est d’utiliser la moyenne et l’écart-type (ou sd) lorsque les données suivent une distribution normale, et la médiane et l’intervalle interquartile (IQR), si les données ne suivent pas une loi normale.

Afin d’obtenir les variables pour lesquelles le test de Shapiro-Wilk est significatif (rejet de l’hypothèse de normalité), nous pouvons employer ce code :

library(purrr)
mydata %>%
    dplyr::select_if(is.numeric) %>%
    as.list() %>%
    map(shapiro.test)%>%
    keep(~ .x$p.value < 0.05)
## $age
## 
##  Shapiro-Wilk normality test
## 
## data:  .x[[i]]
## W = 0.94104, p-value = 2.375e-07
## 
## 
## $height
## 
##  Shapiro-Wilk normality test
## 
## data:  .x[[i]]
## W = 0.94672, p-value = 7.804e-07
## 
## 
## $weight
## 
##  Shapiro-Wilk normality test
## 
## data:  .x[[i]]
## W = 0.93138, p-value = 3.609e-08 

Ensuite, il est nécessaire de créer un vecteur avec le nom de ces variables, et de les spécifier dans la fonction print(), avec l’argument nonnormal, comme ceci :

var_non_normal <- c("age","height","weight")

print(table_globale , 
      showAllLevels = TRUE,
      nonnormal = var_non_normal)
##                        
##                         level            Overall                
##   n                                         203                 
##   treat (%)             placebo             120 (59.1)          
##                         rIFN-g               83 (40.9)          
##   sex (%)               male                168 (82.8)          
##                         female               35 (17.2)          
##   age (median [IQR])                      12.00 [6.00, 20.00]   
##   height (median [IQR])                  140.00 [114.50, 169.25]
##   weight (median [IQR])                   33.40 [20.25, 58.70]  
##   inherit (%)           X-linked            131 (64.5)          
##                         autosomal            72 (35.5)          
##   steroids (%)          no                  196 (96.6)          
##                         yes                   7 ( 3.4)          
##   propylac (%)          no                   31 (15.3)          
##                         yes                 172 (84.7)          
##   hos.cat (%)           US:NIH               41 (20.2)          
##                         US:other            108 (53.2)          
##                         Europe:Amsterdam     28 (13.8)          
##                         Europe:other         26 (12.8) 

Créer une table one stratifiée

Ici, je vais utiliser la variable treat comme variable de stratification :

table_strat <- CreateTableOne( strata = "treat" , data = mydata )

print(table_strat, 
      showAllLevels = TRUE,
      nonnormal = var_non_normal,
      test=FALSE) 
                 Stratified by treat
                        level            placebo                 rIFN-g                 
  n                                         120                      83                 
  treat (%)             placebo             120 (100.0)               0 (  0.0)         
                        rIFN-g                0 (  0.0)              83 (100.0)         
  sex (%)               male                100 ( 83.3)              68 ( 81.9)         
                        female               20 ( 16.7)              15 ( 18.1)         
  age (median [IQR])                      11.50 [5.00, 21.25]     12.00 [7.00, 18.50]   
  height (median [IQR])                  140.05 [107.85, 169.77] 140.00 [119.95, 166.50]
  weight (median [IQR])                   33.40 [18.10, 63.55]    34.40 [22.25, 52.00]  
  inherit (%)           X-linked             74 ( 61.7)              57 ( 68.7)         
                        autosomal            46 ( 38.3)              26 ( 31.3)         
  steroids (%)          no                  114 ( 95.0)              82 ( 98.8)         
                        yes                   6 (  5.0)               1 (  1.2)         
  propylac (%)          0                    20 ( 16.7)              11 ( 13.3)         
                        1                   100 ( 83.3)              72 ( 86.7)         
  hos.cat (%)           US:NIH               20 ( 16.7)              21 ( 25.3)         
                        US:other             67 ( 55.8)              41 ( 49.4)         
                        Europe:Amsterdam     16 ( 13.3)              12 ( 14.5)         
                        Europe:other         17 ( 14.2)               9 ( 10.8)          

Améliorer une table one stratifiée

Vous pouvez choisir d’afficher les p-values des comparaisons entre les strates, en employant l’argument test=TRUE et exact=TRUE (permet de faire des tests de Fisher à la place des tests du Chi2, quand le nombre de données est trop faible)

print(table_strat, 
	  showAllLevels = TRUE,
	  nonnormal = var_non_normal,
	  test=TRUE) 
                       Stratified by treat
                        level            placebo                 rIFN-g                  p     
  n                                         120                      83                        
  treat (%)             placebo             120 (100.0)               0 (  0.0)          <0.001
                        rIFN-g                0 (  0.0)              83 (100.0)                
  sex (%)               male                100 ( 83.3)              68 ( 81.9)           0.943
                        female               20 ( 16.7)              15 ( 18.1)                
  age (median [IQR])                      11.50 [5.00, 21.25]     12.00 [7.00, 18.50]     0.750
  height (median [IQR])                  140.05 [107.85, 169.77] 140.00 [119.95, 166.50]  0.632
  weight (median [IQR])                   33.40 [18.10, 63.55]    34.40 [22.25, 52.00]    0.736
  inherit (%)           X-linked             74 ( 61.7)              57 ( 68.7)           0.381
                        autosomal            46 ( 38.3)              26 ( 31.3)                
  steroids (%)          no                  114 ( 95.0)              82 ( 98.8)           0.287
                        yes                   6 (  5.0)               1 (  1.2)                
  propylac (%)          0                    20 ( 16.7)              11 ( 13.3)           0.641
                        1                   100 ( 83.3)              72 ( 86.7)                
  hos.cat (%)           US:NIH               20 ( 16.7)              21 ( 25.3)           0.447
                        US:other             67 ( 55.8)              41 ( 49.4)                
                        Europe:Amsterdam     16 ( 13.3)              12 ( 14.5)                
                        Europe:other         17 ( 14.2)               9 ( 10.8)                
                       Stratified by treat
                        test   
  n                            
  treat (%)                    
                               
  sex (%)                      
                               
  age (median [IQR])    nonnorm
  height (median [IQR]) nonnorm
  weight (median [IQR]) nonnorm
  inherit (%)                  
                               
  steroids (%)                 
                               
  propylac (%)                 
                               
  hos.cat (%)                  
                               
                               
                                

Exporter une table one

Ici, je commence par créer un dossier “resultats”, puis j’exporte la table one, dans ce dossier, en employant la fonction  write.csv2().

ma_table_strat <- print(table_strat, 
	  showAllLevels = TRUE,
	  nonnormal = var_non_normal,
	  test=TRUE)
dir.create("resultats")
write.csv2(ma_table_strat, here::here("resultats/ma_table_strat.csv")) 

Et voilà !

Conclusion

Je vous laisse essayer ce package,  et n’hésitez pas à me faire des retours en laissant un commentaire.

Si vous voulez en savoir plus sur l’utilisation de ce package `tableone`, vous pouvez consulter sa vignette en cliquant ici.

Si cet article vous a plu, ou vous a été utile, vous pouvez le partager,  et soutenir le blog en réalisant un don libre sur la page Tipeee.

Poursuivez votre lecture

3 réponses

    1. Bonjour David,

      dans la page d’aide de la fonction CreateTableOne, vous trouverez les infos suivantes :
      testApprox = chisq.test,
      argsApprox = list(correct = TRUE),
      testExact = fisher.test,
      argsExact = list(workspace = 2 * 10^5),
      testNormal = oneway.test,
      argsNormal = list(var.equal = TRUE),
      testNonNormal = kruskal.test,

      Je comprends que, par défaut, c’est un test t quand il ya 2 groupes et que les données sont quantitatives, une anova quand il y a plus de 2 groupes, et un test du chi2 pour les données qualitatives.
      Je vous recommande de faire des tests pour être bien sûr (notamment pour vérifier l’utilisation de l’anova ou du test de Kruskall Wallis).
      Vous pouvez aussi jeter un coup d’oeil au package gtsummary que j’utilise à présent.
      Bonne continuation.

  1. Bonjour, merci beaucoup pour ces efforts.
    Dis moi y’a t’il un script pour associer l’apparition des lettres pour la séparation des médianes de Dunntest du packages FSA???

Laisser un commentaire

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

Bonjour !

vous venez souvent ?

Identifiez-vous pour avoir accès à toutes les fontionnalités !

Aide mémoire off'R ;)

Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.