Les tableaux statiques pour vos rapports en R

Tags : Autour de R, Ressources
Date :

Les tableaux ont toujours été utilisés pour présenter des données, des résultats d’analyses statistiques, quand on doit voir les chiffres noir sur blanc. Quand on code en R, on n’en a pas particulièrement besoin, mais dès qu’on parle de reporting ou de PDF via RMarkdown, la question de la représentation des tables se pose souvent, et elles sont souvent combinées à des éléments de dataviz. Quelques packages y sont dédiés, petit tour d’horizon…

Tables statiques dans RMarkdown pour un document PDF

Dans un souci de lisibilité de cet article, je ne vous présenterai ici que les 6 premières lignes du jeu de données iris et mtcars. On utilisera aussi les données starwars du package {dplyr} :

library(dplyr)
data("starwars")

Quand on souhaite restituer son travail à l’aide de rapports automatisés, on peut le faire depuis R grâce à RMarkdown. Vous vous souvenez, on vous parlait de {bookdown} il n’y a pas si longtemps dans “Rédiger avec bookdown : pourquoi ? comment ?”. Et pour sortir un beau document PDF tout plein de graphes R et de tables, vous pouvez spécifier l’affichage des tables notamment dans l’en-tête YAML de votre fichier RMarkdown :

output:
  pdf_document:
    df_print: default

On obtient :

head(iris)


Pas joli joli…. C’est la sortie R de la console. Si je modifie l’en-tête YAML par:

output:
  pdf_document:
    df_print: kable

(ce qui est équivalent à utiliser knitr::kable() dans un chunk)

La table précédente devient :


C’est déjà mieux ! Mais on peut créer des tables beaucoup plus funky.

La fonction kable() et le package {kableExtra}

Ce package nous permet de créer des tables complexes, tout en y appliquant des styles. Il importe le symbole pipe %>% de {magrittr} : on peut ajouter des “couches” à une sortie kable().

# Installation de la library
install.packages("kableExtra")
# Chargement des libraries
library(knitr)
library(kableExtra)

La fonction kable() pour un affichage de tableaux simples et efficaces

Quand on crée une table en Rmakdown dans un format PDF, on utilise une distribution LaTeX, dont le style usuel est plutôt affreux :

head(iris) %>%
  kable(format = "latex")


En mettant le paramètre booktable à TRUE, le résultat est un peu plus satisfaisant, on revient à l’appel simple de la fonction kable() :

head(iris) %>%
  kable(format = "latex", booktable = TRUE)


Il est également possible d’ajouter un titre numéroté à notre table, grâce au paramètre caption de la fonction kable() :

head(iris) %>%
  kable(format = "latex", booktable = TRUE, caption = "Ma table")


Attention, dans ce cas, la table sera replacée à l’endroit considéré le plus pertinent par LateX dans votr document, et non à l’endroit exact où nous l’avons placée dans notre code.

Donner du style à vos tableaux avec kable_styling()

Ok, donc avec la fonction kable(), on ne peut pas vraiment aller plus loin. C’est là qu’entre en jeu le package {kableExtra}, dont la fonction kable_styling() permet de styliser un peu notre table, comme par exemple via le paramètre latex_options :

head(iris) %>%
  kable("latex", booktabs = T)%>%
  kable_styling(latex_options = "striped")


Si j’ajoute l’option LaTeX HOLD_position, je peux ajouter un titre à ma table et faire en sorte qu’elle reste à l’endroit exact où je l’ai créée :

head(iris) %>%
  kable("latex", booktabs = T, caption = "Ma table")%>%
  kable_styling(latex_options = c("striped", "HOLD_position"))

Dans le cas où j’ai une table avec un grand nombre de colonnes, je peux utiliser l’option scale_down qui va permettre un ajustement de la table à la taille de la page. Prenons par exemple les données starwars du package {dplyr} :

library(dplyr)
data("starwars")
star2 <- starwars %>%
  select(-(films:starships)) %>%
  head()

Sans l’option, toutes les colonnes ne s’affichent pas :

star2 %>%
  kable("latex", booktabs = T)%>%
  kable_styling(latex_options = "striped")


Avec scale_down :

star2 %>%
  kable("latex", booktabs = T)%>%
  kable_styling(latex_options = c("striped", "scale_down"))


Dans le cas où la table à afficher contient trop de lignes pour être contenue dans une seule page, on peut répéter les noms de colonnes à chaque page, via l’option repeat_header et le paramètre longtable :

iris %>%
  kable("latex", longtable = TRUE, booktabs = TRUE) %>%
  kable_styling(latex_options =c("repeat_header"))

Un autre paramètre intéressant de la fonction kable_styling() : full_width, qui quand il est mis à TRUE permet d’étendre une table sur toute la largeur de la page :

head(iris) %>%
  kable("latex", booktabs = T)%>%
  kable_styling(full_width = TRUE)

On peut également noter le paramètre font_size qui permet d’indiquer la taille des caractères de la table :

head(iris) %>%
  kable("latex", booktabs = T) %>%
  kable_styling(font_size = 6)

Des colonnes et des lignes stylées, en couleur, italique, gras, …

Et si on ajoutait un peu de couleurs maintenant ? et un peu plus de style ? Prenons les données star2. Je souhaite mettre la colonne name en gras, la colonne species en rouge, la première ligne en italique, blanc et sur fond noir, changer l’orientation et la couleur des noms de colonnes :

  • la fonction column_spec permet de spécifier le style d’une ou plusieurs colonnes
  • la fonction row_spec permet de spécifier le style d’une ou plusieurs lignes
head(star2) %>%
  kable("latex", booktabs = TRUE) %>%
  kable_styling(latex_options = "scale_down") %>%
  column_spec(1, bold = TRUE) %>%
  column_spec(11, color = "red") %>%
  row_spec(1, bold = T, color = "white", background = "black", italic = TRUE) %>%
  row_spec(0, angle = 45, bold = TRUE, color = spec_color(1:11, end = 0.9, option = "A", direction = -1))


Pas mal non ?

Complexifier la structure avec de multiples en-tête et des cellules fusionnées

{kableExtra} permet aussi de réaliser des tables un peu plus complexes en termes de structure :

  • add_header_above() permet de grouper les colonnes et d’ajouter une seconde ligne contenant le nom des groupes

Par exemple, avec les données iris :

head(iris) %>%
  kable("latex", booktabs = TRUE) %>%
  kable_styling(latex_options = "striped") %>%
  add_header_above(c("Sepal" = 2, "Petal" = 2, " " = 1), italic = TRUE)


  • pack_rows() permet de grouper les lignes

Par exemple avec les données mtcars :

mtcars[1:10, 1:6] %>%
  kable("latex", booktabs = T) %>% 
  kable_styling() %>%
  pack_rows("Group 1", 4, 7) %>%
  pack_rows("Group 2", 8, 10)


Il est également possible de grouper les lignes d’une autre façon, en utilisant la fonction collapse_rows() :

mtcars[1:10, 1:6] %>%
  mutate(Groupe = c(rep("", 3), rep("Group 1", 4), rep("Group 2", 3)), 
         name = rownames(.), .before = mpg) %>%
  kable("latex", booktabs = T) %>% 
  collapse_rows(columns = 1, valign = "middle", latex_hline = "major")


Ajout de notes de bas de tableau

On peut également **ajouter des notes en bas du tableau*, via la fonction footnote() :

head(iris) %>%
  kable("latex",  booktabs = TRUE) %>%
  footnote(general = "Commentaire général de la table",
           number = c("note 1; ", "note 2; "),
           alphabet = c("note A; ", "note B; "),
           symbol = c("symbole 1; ", "symbole 2"),
           title_format = c("italic", "underline"))


Ce package vous plaît ? En savoir plus sur kableExtra

Le package {gt} pour formater vos tableaux

{gt}, pour great table. C’est un package relativement récent, puissant et simple d’utilisation. La fonction de base, gt(), appelée sans paramètres autres que le jeu de données, nous donne le même rendu que la fonction kable() du package {knitr} :

library(gt)
head(iris) %>%
  gt()


Les éléments d’une table gt


En-tête, notes de bas de tableau, pied de page et sources

Tout comme avec le package {kableExtra}, il est possible de construire nos tables via le pipe %>%. Les éléments extérieurs à la table tels que titre, sous-titre, footnote et sources peuvent être ajoutés via les fonctions de type tab_X() :

  • tab_header() pour le titre et le sous-titre
  • tab_footnote() pour les notes de pied de page, appelée pour chaque référence à un ou plusieurs éléments de la table
  • tab_source_note pour les sources, cette fonction peut être appelée autant de fois que l’on a de sources

Par exemple :

head(iris) %>%
  gt() %>%
  tab_header(title = "Données Iris", 
             subtitle = "Premières lignes"
  ) %>%
  tab_footnote(footnote = "Colonne Species", 
               locations = cells_column_labels(
                 columns = vars(Species))) %>%
  tab_source_note("Source : package datasets")


Ces fonctions permettent également d’entrer du Markdown pour formater votre texte en gras, italique, équations, … à la place d’un simple texte, via la fonction md(), ou du HTML via la fonction html() :

head(iris) %>%
  gt() %>%
  tab_header(title = md("Données **Iris**"), 
             subtitle = md("*Premières lignes*")) %>%
  tab_footnote(footnote = "Colonne Species", 
               locations = cells_column_labels(
                 columns = vars(Species))) %>%
  tab_source_note(md("Source : package `{datasets}`"))


Les “footnotes” font référence à une ou plusieurs cases de notre table, qui sont spécifiées par l’argument locations de la fonction tab_footnote(), avec :

  • cells_body() : prend en arguments columns et rows qui peuvent être des vecteurs de noms de colonnes et de lignes (char), des vecteurs d’indices, ou une fonctions de sélection comme start_with(), ends_with(), contains(), …
  • cells_column_labels() pour cibler les noms des colonnes
  • cells_row_groups()

Le “stub” pour gérer les titres et les groupes de lignes

C’est toute la partie qui concerne les noms de lignes, dans la zone gauche du tableau. Un moyen simple de générer cette zone consiste à le déclarer lors de l’appel à la fonction gt() via le paramètre rowname_col. La fonction tab_stubhead() permet quant à elle d’ajouter un label aux noms de lignes. Par exemple avec les données mtcars :

mtcars %>%
  mutate(name = rownames(.)) %>%
  head() %>%
  gt(rowname_col = "name") %>%
  tab_stubhead(label = "Car name")


Les noms des lignes ne constituent pas une colonne à proprement parler, attention donc lorsque vous appellerez la fonction tab_footnote().

Complexifier la structure avec des titres, des groupes de colonnes et de lignes

De manière similaire à la fonction add_header_above() du package {kableExtra}, il est possible de créer des groupes de colonnes, via la fonction tab_spanner() :

head(iris) %>%
  gt() %>%
  tab_spanner(label = "Sepal", columns = c(1, 2)) %>%
  tab_spanner(label = "Petal", columns = c(3, 4))


Comme avec {kableExtra} et sa fonction pack_rows(), on peut ici créer des groupes de lignes, grâce à la fonction tab_row_group() :

mtcars[1:10, 1:6] %>%
  mutate(name = rownames(.)) %>%
  gt(rowname_col = "name") %>%
  tab_stubhead(label = "Car name") %>%
  tab_row_group(group = "Group 2", rows = 8:10) %>%
  tab_row_group(group = "Group 1", rows = 4:7) %>%
  tab_row_group(group = " ", rows = 1:3)


Vous noterez qu’il faut écrire les groupes dans l’ordre inverse à leur position dans la table.

Styliser sa table avec les couleurs et autres styles

C’est ici un peu plus complexe qu’avec le package {kableExtra} : il faudra passer par la fonction tab_options() et ses nombreux paramètres :

https://gt.rstudio.com/reference/tab_options.html

Par exemple : https://gist.github.com/rich-iannone/1da1ae7a7203958a0c5b1bd1d4b24017

Et ici, pour en savoir plus sur le package {gt}, avec des cas d’application plus poussés.

Le package {flextable} pour des tables dans Word et Powerpoint

Il vous sera utile pour générer des tables au format natif Microsoft Word / Powerpoint ou bien dans le cas où vous souhaitez générer votre document PDF via le package {pagedown}.

Je vous laisse aller jeter un oeil à la page du package {flextable} si vous souhaitez en savoir plus.

La suite…

Même si ces tables statiques sont préconisées pour les documents PDF ou Word, il est tout à fait possible de les intégrer dans une application Shiny ou un document HTML. Mais il existe un certain nombre de packages dédiés à la représentation de tables interactives, qui peuvent devenir un outil puissant de visualisation. La suite donc, au prochain numéro…


À propos de l'auteur


Commentaires

Laisser un commentaire

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


À lire également