Trucs pour LaTeX & R

Créer un tableau résumant votre étude

lundi 18 septembre 2017 par Philippe MICHEL

25/02/2017 : Amélioration de la définition du longtable (pas encore parfait)

Tables - code complet

Pour l’exemple nous allons créer un tableau habituel dans un article médical : comparaison de deux groupes (traités / non traités par exemple) en donnant pour chaque variable la moyenne & l’écart type pour les données numériques, le nombre & le pourcentage pour les données discrètes, enfin le p. Ce qui donne (en moche) :

traiténon traitép
Âge 55,2 $pm$ 10,5 48,7 +/- 14,5 0,04
Sexe = M 44/110 (35%) 48/112 (36%) 0,75

Le script peut se résumer à :

Initialisation du tableau
Pour chaque colonne :
    Si numérique :
         Calcul moyenne, écart-type, p.
         Création de la ligne & ajout au tableau
    Si variable discrète :
         Calcul des % pour chaque modalité & du chi2  
          Si dichotomique :
                     Création de la ligne & ajout au tableau
          Plus de deux niveau :
                     Ligne nom variable, p
                     Création de la ligne & ajout au tableau
                     Pour chaque valeur de la variable de tri :
                                 Ligne avec les n & %.
                                 Création de la ligne & ajout au tableau
création du titre (avec les niveaux de la variable de tri)
Transformation du tableau en LaTeX

Nous partons donc d’un data-frame nommé tt, bien préparé. Un tableau simple descriptif a déjà été réalisé. Nous allons créer un tableau reprenant toutes les variables, les comparer entre les différents groupes (il y a donc une variable de test appelée ici vtri & ayant deux niveaux oui & non). L’exemple a deux modalités ce qui est le cas le plus fréquent mais il peut il y en avoir plus. D’où l’utilisation d’une Anova pour la comparaison & non un simple Student.

l’affichage doit comprendre :

  • Pour les variables numériques : moyenne +/- écart type avec le bon symbole +/-
  • Pour les variables discrètes : nombre (pourcentage)
  • On verra aussi une variante avec un test non paramétrique (Wilcoxon) avec affichage des médianes & des quartiles.

Tout d’abord il faut initialiser la boucle qui va parcourir toutes les variables du data.frame & créer un tableau vide.

vtri la variable de tri
tt le data.frame étudié

  1. lvtri <- length(levels(vtri))# Nb de modalité de la variable de tri
  2. mlig <- matrix(nrow=0,ncol=lvtri+2)# création de la matrice
  3. #
  4. # ...
  5. # tout le traitement par ligne
  6. # ...
  7. }
  8. # Transformation du tableau en LaTeX grâce à xtable
  9. xtable(tabf) # ... (voir plus bas)

Télécharger

une ligne moyenne écart-type

Nous allons donc calculer la moyenne & l’écart-type pour chacune des modalités de notre variable de test. La fonction agregate est là pour ça :

  1. aggregate(etude$age,by=list(traitement),FUN="mean",na.rm=T)
  2. Group.1 x
  3. 1 Non 38.47826
  4. 2 Oui 36.94286

Télécharger

Qui nous renvoie un tableau avec, en première colonne les niveaux de la variable de test & en seconde colonne la moyenne pour chacun de ces niveaux.

Comme il n’y a que deux niveaux on aurait pu utiliser le t de Student (la fonction t.test vous donne les moyennes des deux groupes comparées) mais aggregate a deux qualités : on utilisera la même méthode pour calculer l’écart-type & de plus on pourra faire des tableaux avec des variables de tri à plus deux niveaux.

Donc on va extraire les données du tableau. Créons donc une petite boucle qui va afficher la moyenne et l’écart-type :

vart est la colonne du data.frame en cours.
vtri la variable de tri

  1. if (is.numeric(vart)){ print("num")
  2. agm <- aggregate(vart~vtri,FUN="mean",na.rm=T)
  3. ags <- aggregate(vart~vtri,FUN="sd",na.rm=T)
  4. for (j in 1:lvtri){ #pour chaque modalité
  5. moy <- round(agm[j,2],2)
  6. etyp <- round(ags[j,2],2)
  7. dlig <- c(dlig,paste0(moy,"\\pm ",etyp)) # On allonge la ligne
  8. }
  9. ll <- anova(lm(vart~vtri))[5]
  10. lla <-ll[1,1]
  11. lla <- signif(lla,3)
  12. dlig <- c(dlig,lla)
  13. tabf <- rbind(tabf,dlig) #ajout de la ligne au tableau
  14. }

Télécharger

En reprenant le code : On calcule les moyennes & les écarts-type ainsi que le nombre de niveau de la variable de tri (ici 2). Puis on initie la ligne (un vecteur) avec le nom de la variable (un peu bête dans cet exemple mais ça va servir plus tard). Dans la boucle on extrait pour chaque ligne le nombre voulu, on le formate pour avoir un affichage clair puis on l’ajoute à la ligne dans le vecteur.

Il ne reste qu’à faire un anova, en extraire le p & l’inclure dans le vecteur. Et voilà une belle ligne.

Non paramétrique

Le même pour un test non paramétrique & une présentation en médiane & quartiles. (ne fonctionne que pour deux modalités).

  1. if (is.numeric(vart)){
  2. qo <- quantile(vart[vtri=="oui"],na.rm=T)
  3. qn <- quantile(vart[vtri=="non"],na.rm=T)
  4. mo <- paste0(qo[3]," [",qo[2],"-",qo[4],"]")
  5. mn <- paste0(qn[3]," [",qn[2],"-",qn[4],"]")
  6. dlig <- c(dlig,mo,mn) # On allonge la ligne
  7. ll <- wilcox.test(vart~vtri)
  8. ll <- ll$p.value
  9. lla <- signif(ll,3)
  10. dlig <- c(dlig,lla)
  11. mlig <- rbind(mlig,dlig) #ajout de la ligne au tableau
  12. }

Télécharger

Une ligne nombre/pourcentage

Nous allons un peu compliquer les choses : nous allons avoir un affichage simple sur une ligne pour les variables dichotomiques en affichant une seule modalité. L’en-tête de la ligne sera donc le nom de la variable suivi de la modalité affichée sauf si l’on est en Oui/Non auquel cas on affiche le Oui.

Si la variable a plus de deux modalités on affiche une ligne avec son nom & le p global, ensuite la répartition modalité par modalité :

Sexe (M)44(55%)48 (48%)0,45
Hypertendu 88 (74 %) 54 (47 %) 0,054
Couleur des cheveux 0,88
_____blond 45 (55 %) 48 (57 %)
_____brun 38 (35 %) 47 (36 %)
_____roux 5 (10 %) 35 (7 %)

Je vous laisse rendre le résultat lisible en LaTeX en jouant sur des traits, des couleurs etc.

Petit préalable : toutes les variables factorielles en Oui/Non doivent être transformés au préalable en variable ordonnées avec Oui en premier niveau par :

  1. > levels(vaccin)
  2. [1] "Non" "Oui"
  3. > vaccin <- relevel(vaccin,"Oui")
  4. > levels(vaccin)
  5. [1] "Oui" "Non"

Télécharger

Je vous laisse écrire la boucle avec un test pour appliquer ça à toute votre base de donnée.

  1. vart <- as.factor(vart)
  2. if (length(levels(vart))>1){ # On évite les valeurs constantes
  3. tb <- table(vtri,vart) # on crée un tableau croisé
  4. tbm <- margin.table(tb,1) # Sommes par ligne
  5. clig <- chisq.test(vart,vtri)$p.value # Calcul du Chi2
  6. clig <- signif(clig,3)
  7. #
  8. # Variables à 2 niveaux
  9. #
  10. if (length(levels(vart)) == 2){
  11. if(levels(vart)[1] != "oui"){ # Complément du nom de variable
  12. dlig <- paste0(dlig, " (",levels(vart)[1],")")
  13. }
  14. for (j in 1:lvtri){
  15. nn <- tb[j,1]
  16. pn <- signif(100*nn/tbm[j],3)
  17. dlig <- c(dlig,paste0(nn," (",pn,"\\, \\%)")) }
  18. dlig <- c(dlig,clig)
  19. tabf <- rbind(tabf,dlig) #ajout de la ligne au tableau
  20. }
  21. #
  22. # Variables à plus de 2 niveaux
  23. #
  24. else {
  25. tlig <- c(names(tt[l]),rep(" ",lvtri),clig)
  26. tabf <- rbind(tabf,tlig)
  27. for (i in 1:length(levels(vart))){ #Pour chaque niveau de la variable
  28. dlig <- paste0("~~~~~",levels(vart)[i])
  29. for (j in 1:lvtri){
  30. nn <- tb[j,i]
  31. pn <- signif(100*nn/tbm[j],3)
  32. dlig <- c(dlig,paste0(nn," (",pn,"\\, \\%)"))
  33. }
  34. dlig <- c(dlig," ")
  35. tabf <- rbind(tabf,dlig) #ajout de la ligne au tableau
  36. }}
  37. }

Télécharger

On crée d’abord un tableau croisant la variable à étudier avec la variable tri, on calcule les totaux des lignes avec margin.table. la suite des calculs est simple, un chi2 pour finir, enfin on monte la ligne comme pour les moyennes.

Pour les variables a plus de deux niveaux on va d’abord créer la ligne contenant le nom de la variable , des cases vides & le p global puis la transformer en une matrice d’une ligne.
Ensuite une boucle va prendre toutes les modalités de la variable de test pour chacune créer une ligne, faire les calculs comme plus haut et ensuite ajouter cette ligne à la matrice (fonction rbind). Et voilà.

Construire le tableau

Il reste maintenant à transformer le tableau en LaTeX avec le bon en-tête.

  1. library(xtable)
  2. #Création de la ligne de titre
  3. ltit <- paste0("&\\text{",paste(levels(vtri),collapse="}&\\text{"),"}&p\\\\")
  4. # Transformation du tableau en LaTeX via le package [*xtable*]
  5. xlig <- xtable(mlig)
  6. #
  7. print(xlig,
  8. tabular.environment='longtable',
  9. include.colnames=FALSE,
  10. floating=FALSE,
  11. booktabs=TRUE,
  12. hline.after=-1,
  13. include.rownames=FALSE,
  14. sanitize.text.function = function(x){x},
  15. add.to.row = list(pos = list(0),
  16. command =
  17. paste0(ltit,
  18. "
  19. \\midrule
  20. \\endfirsthead
  21. \\midrule
  22. ",
  23. ltit,
  24. "
  25. \\midrule
  26. \\endhead
  27. \\bottomrule
  28. \\endfoot
  29. \\bottomrule
  30. \\caption{}
  31. \\label{tab}
  32. \\endlastfoot
  33. ")
  34. )
  35. )

Télécharger

Il reste à préciser la légende & le label. À moins de mettre dans la définition de fonction une variable pour le label.
Derneir problème : je n’ai toujours pas compris comment indiquer la composition des colonnes. Il sort donc quelque chose comme :

  1. \begin{longtable}{llll}

à corriger manuellement, désolé ! Personnellement j’utilise une commande de défiinition de colonnes en mode math nommée « C » & le type « S » du package siunitx pour le petit p soit :

  1. \newcolumntype{C}{>{$}c<{$}}
  2. .....
  3. \begin{longtable}{lCCS}

Télécharger

À vous de jouer !


Accueil | Contact | Plan du site | | Statistiques du site | Visiteurs : 195 / 125759

Suivre la vie du site fr  Suivre la vie du site kntitr   ?    |    titre sites syndiques OPML   ?

Site réalisé avec SPIP 3.2.0 + AHUNTSIC

Creative Commons License