Présenter les agrégations sous forme de tableaux croisés

Les packages nécessaires

Nous allons avoir besoin de charger quelques packages pour réaliser notre tableau.

library(tidyverse)
library(flextable)
library(officer)
use_df_printer()

Le sous jeu de données

Une agrégation d’un sous jeu de données issue de ggplot2::diamonds va être utilisé pour définir le contenu du flextable.

Le code ci-dessous permet de filtrer certaines données afin que notre illustration ne contienne pas de nombreuses colonnes.

dat <- ggplot2::diamonds |>
  filter(
    cut %in% c("Good", "Very Good"),
    clarity %in% c("I1", "SI1", "VS2")
  ) |> 
  mutate(price = price / 1000)
dat

L’agrégation principale

Maintenant, agrégeons l’ensemble de données filtrées et comptons les observations. Le tableau de données créé aura trois dimensions, cut, color et clarity, qui seront utilisées comme lignes ou colonnes dans le flextable final.

summary_dat <- dat |>
  group_by(cut, color, clarity) |>
  summarise(
    y_mean = mean(price, na.rm = TRUE),
    y_sd = sd(price, na.rm = TRUE),
    .groups = "drop"
  )
summary_dat

Les autres agrégations

Les comptages suivants seront utilisés pour montrer les comptages dans les lignes.

cut_counts <- count(dat, cut, name = "n_cut")
cut_counts

Les comptages suivants seront utilisés pour montrer les comptages dans les colonnes.

clarity_counts <- count(dat, clarity, name = "n_clarity")
clarity_counts

Les valeurs de formattage par défaut

Cette étape n’est pas obligatoire, elle définit certaines valeurs par défaut pour les flextables qui seront produit ultérieurement.

init_flextable_defaults()
set_flextable_defaults(
  theme_fun = theme_booktabs,
  big.mark = " ", font.color = "#333333",
  border.color = "#333333",
  padding = 3,
)

Utilisation de la fonction tabulator

Maintenant que tous les jeux de données sont prêts à être utilisés, appelons la fonction tabulator() qui va préparer un objet qui sera envoyé à as_flextable().

ftd <- fp_text_default(color = "#f24f26")

# create tabulator object to be used with `as_flextable()` ----
tab <- tabulator(
  x = summary_dat,
  rows = c("cut", "color"),
  columns = "clarity",
  hidden_data = cut_counts,
  row_compose = list(
    cut = as_paragraph(cut, as_chunk(x = paste0("\nn = ", n_cut), props = ftd))
  ),
  # defines the only cells to show in the result
  `y stats` = as_paragraph(y_mean, " (\u00B1 ", y_sd, ")")
)


## get colkeys corresponding to multiple "y stats" ----
colkeys <- tabulator_colnames(tab, columns = "y stats")
colkeys
## [1] "I1@y stats"  "SI1@y stats" "VS2@y stats"

Le flextable

Un flextable peut facilement être produit avec le code suivant:

ft <- as_flextable(tab, separate_with = "cut")
ft

Personnalisation du tableau

Il faut que nous ajoutions les comptages dans les colonnes.

ft <- append_chunks(ft, 
  j = colkeys, i = 1, part = "header",
  as_paragraph(
    "\n",
    as_chunk(x = paste0("(n = ", clarity_counts$n_clarity, ")"), props = ftd)
  )
)
ft

Ajoutons un titre :

ft <- add_header_lines(ft, "Subset of original dataset")
ft

Et ajoutez une ligne spéciale pour que, lors du rendu en Word, le haut du flextable indique le numéro de page correspondant à sa position dans le document.

ft <- add_header_lines(ft, "Page N°") |> 
  append_chunks(i = 1, part = "header", j = 1,
                as_word_field(x = "Page")) |> 
  align(part = "header", align = "right", i = 1) |> 
  set_caption(caption = "Prices of over 50 000 round cut diamonds")

ft

Rendu avec Word

Le code suivant produit un document Word avec le package ‘officer’, le contenu est un faux contenu. Le but est de montrer comment notre flextable est rendu dans un document Word.

psum_txt <- "Lorem ipsum dolor sit amet, purus ut nullam nisl vehicula non ligula sem non. Egestas nascetur, eu sed nec mattis semper arcu auctor sagittis id consequat non? Facilisi vestibulum ac nec primis. Posuere sociis ligula tempor, mattis sed sed dapibus. Taciti nulla mattis aliquet dictumst, nisi aenean, pulvinar! Hendrerit porttitor quis praesent mi nisl lorem mauris ut nulla. Tincidunt in sit sit quisque id molestie. Eros, orci ligula phasellus sed erat vel vivamus penatibus aliquam, scelerisque turpis sociis erat."

landscape_two_columns <- block_section(
  prop_section(
    type = "continuous",
    section_columns = section_columns(widths = c(3, 3))
  )
)

read_docx(path = "template.docx") |> 
  body_add_par(value = "Lorem ipsum", style = "heading 1") |> 
  body_add_par(psum_txt) |> 
  body_add_par(value = "Tempor velit sed", style = "heading 2") |> 
  body_end_block_section(value = block_section(property = prop_section(type = "continuous"))) |> 
  body_add_par(psum_txt) |> 
  body_add_par(psum_txt) |> 
  body_end_block_section(value = landscape_two_columns) |> 
  body_add_par(psum_txt) |> 
  body_add_par(psum_txt) |> 
  body_add_break() |> 
  body_add_par(value = "Mattis potenti metus", style = "heading 2") |> 
  body_add_par(value = "") |> 
  body_add_flextable(value = ft, topcaption = FALSE, keepnext = FALSE) |> 
  body_add_par(psum_txt) |> 
  print(target = "illustration.docx")

Vous pouvez télécharger le document Word: illustration.docx

Après avoir mis à jour les champs dans le document, il a ce rendu :

illustration