R permet d’automatiser des calculs, mais aussi de générer des rapports sous différents formats qui peuvent être facilement partagés (HTML, PDF, etc). Cela se fait grâce à R Markdown (intégré dans RStudio)(cela correspond aux fichiers .Rmd).
R Markdown permet d’écrire son script R pour réaliser les actions souhaitées et d’afficher dans le même document le résultat des actions. Ainsi, il est possible d’afficher uniquement le résultat final souhaité, composé de textes, de tableaux, de graphiques, etc.
Le code Rmarkdown permettant de générer un rapport avec des visualisations de données commence par aller chercher les données qui sont dans un fichier à sélectionner (il s’agit d’un fichier contenant les réponses à un sondage de satisfaction avec les colonnes Date, Motif de visite, Note de satisfaction).
Un document Rmarkdown commence par un bloc contenant les infos du titre du document et d’eventuels parametres à prendre en compte ou à proposer à l’utilisateur (ce bloc commence et finit par ‘- – -‘).
Pour créer des parties dans le documents, il est possible de définir des titres de parties avec « ## » (par exemple : ## Mon Titre de Partie).
Les blocs executant du code R commencent et finissent par 3 backquotes (« `). Il est possible de définir dans les paramètres du bloc (via les {}) si on souhaite que le code R soit affiché ou non dans le document final qui sera généré. Pour ne pas afficher le code, on met include=FALSE. Ainsi, seul le résultat final (correspondant à ce qui serait affiché dans la console) est affiché dans le document généré. A noter que dans ces blocs où le code R est éxécuté, le caractère # correspond à des commentaires.
Pour générer des graphiques, il s’agit de faire appel à la librairie ggplot2. Pour afficher des tableaux de données, il s’agit de passer par la fonction kable de la librairie knitr (knitr::kable()).
Le code du document .Rmd génère le document HTML suivant :
Ci-dessous le code Rmarkdown permettant de générer le rapport :
---
title: "Visualisation des reponses au sondage"
output: html_document
params:
CompleteAnswersOnly:
label: "Ne prendre en compte que les réponses complètes:"
value: NON
input: select
choices: [NON,OUI]
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r echo = FALSE, warning = FALSE, message = FALSE}
#Librairies necessaires
###########################
library(dplyr)
library(stringr)
library(ggplot2)
library(glue)
library(tidyselect)
library(scales)
library(plotly)
#Preparation des donnees
###########################
# Chemin d acces au fichier
chemin_fichier <- choose.files(caption="Selectionner le fichier de donnees")
chemin_fichier <- chemin_fichier[1]
# Import des données à partir du fichier txt (tab)
data_sondage <- read.delim(chemin_fichier, sep ="\t")
# FONCTION pour formatter le texte
formatter_texte <- function(texte){
texte <- texte %>% str_replace_all("[.]", "_") %>% str_replace_all(' ','_') %>% str_replace_all("'","_") %>% str_replace_all("-","_") %>% str_replace_all("/","_") %>% str_replace_all(",","_") %>% str_replace_all("[(]","_") %>% str_replace_all("[)]","_") %>% enc2native() %>% iconv(to='ASCII//TRANSLIT')
return(texte)
}
# Renommer les champs (remplacer les points par des underscores)
colnames(data_sondage) <- formatter_texte(colnames(data_sondage))
# Pour le parametre CompleteAnswerOnly
if(params$CompleteAnswersOnly == "OUI"){
data_visualisation <- data_sondage %>% filter(Statut == "Complet" )
} else {
data_visualisation <- data_sondage
}
#Affichage du tableau de données
glue("Les réponses au sondage :")
knitr::kable(data_visualisation, align=rep('c', 3))
```
## Infos sur le sondage
```{r echo = FALSE, warning = FALSE, message = FALSE}
#Generation du texte et des graphiques
###########################
# Periode du questionnaire
dtMin <- data_visualisation[["Date"]] %>% as.Date(format = "%d/%m/%Y") %>% min() %>% format(format="%d/%m/%Y")
dtMax <- data_visualisation[["Date"]] %>% as.Date(format = "%d/%m/%Y") %>% max() %>% format(format="%d/%m/%Y")
glue("Periode de collecte des reponses : Du {dtMin} au {dtMax}")
# Rappel des parametres
glue("Rappel des parametres :
- Prendre en compte que les réponses complètes : {params$CompleteAnswersOnly}
")
```
## Satisfaction
```{r echo = FALSE, warning = FALSE, message = FALSE}
# Nombre reponses a la question de satisfaction
nom_question <- "Quelle_est_votre_satisfaction"
nb_rep <- data_visualisation[nom_question] %>% filter(is.na(.data[[nom_question]]) == FALSE & .data[[nom_question]] != "") %>% nrow()
glue("Nombre de repondants à la question : {nb_rep}")
# FONCTION pour generer les graphiques simples
visualisation_barres <- function(data_visualisation, nom_question, color_fill = "#AED6F1", tri_asc = TRUE, tri_aide = FALSE){
# Formatter le nom de question pour qu il corresponde a celui de la table
nom_question <- formatter_texte(nom_question)
# Préparation du tableau pour decompte
# Recuperation des reponses possible (en valeur brute, differente de la valeur dans le nom de colonne)
index_colonne_question <- which(colnames(data_visualisation) == nom_question)
reponses_possibles <- data_visualisation[nom_question] %>% unique()
# Compiler les decomptes dans une table pour les visualisation
data_graph <- data_visualisation[] %>% filter(.data[[nom_question]] != "") %>% count(.data[[nom_question]])
colnames(data_graph)[1] <- "Reponse"
colnames(data_graph)[2] <- "Decompte"
# Ajout du nombre de repondants pour calculer le ratio
total_repondants <- data_visualisation[ data_visualisation[nom_question] != "" ,index_colonne_question] %>% length()
data_graph[,3] <- total_repondants %>% as.numeric()
colnames(data_graph)[3] <- 'Total_repondants'
data_graph[,4] <- data_graph[,2] / data_graph[,3]
colnames(data_graph)[4] <- 'Ratio'
## Tri de donnees du plus petit au plus grand
if( tri_asc == TRUE){
aide_data_graph <- data_graph %>% arrange(desc(Ratio)) %>% select(Reponse)
data_graph <- data_graph %>% mutate(Reponse=factor(Reponse, levels=aide_data_graph[["Reponse"]]))
} else if(tri_asc == "CUSTOM" & is.vector(tri_aide) == TRUE){
data_graph <- data_graph %>% mutate(Reponse=factor(Reponse, levels=tri_aide))
}
#
# Generation du graphique
#
graph_question <- ggplot(data=data_graph, aes(x=Reponse, y=Ratio)) +
geom_bar(stat="identity", width = 0.5, fill = color_fill) +
# ggtitle(titre) +
theme_minimal() +
coord_flip() +
theme(axis.text.x = element_text(angle = 0, hjust = 1, vjust=1)) +
theme( axis.title.x = element_blank(), axis.title.y = element_blank() ) +
scale_y_continuous(labels=scales::percent)
# Retourner le graphique a la fin
return(graph_question )
}
#
# 1ere partie
#
nom_question <- "Quelle_est_votre_satisfaction"
visualisation_barres(data_visualisation, nom_question, tri_asc=FALSE, color_fill="#A6ACAF") %>% ggplotly() %>% config(modeBarButtonsToRemove = c("lasso2d", "pan2d", "zoom2d"))
#
# 2eme partie
#
# FONCTION pour barres avec 2eme champ
visualisation_barres_avec_2eme_champ_filtre <- function(data_visualisation, nom_question, deuxieme_champ, color_fill = "#AED6F1", tri_asc = TRUE, tri_aide = FALSE){
# Formatter le nom de question pour qu il corresponde a celui de la table
nom_question <- formatter_texte(nom_question)
# Préparation du tableau pour decompte
# Recuperation des reponses possible (en valeur brute, differente de la valeur dans le nom de colonne)
index_colonne_question <- which(colnames(data_visualisation) == nom_question)
index_deuxieme_champ <- which(colnames(data_visualisation) == deuxieme_champ)
reponses_possibles <- data_visualisation[nom_question] %>% unique()
# Compiler les decomptes dans une table pour les visualisation
data_graph <- data_visualisation[] %>% filter(.data[[nom_question]] != "" & .data[[deuxieme_champ]] != "") %>% count(.data[[nom_question]])
colnames(data_graph)[1] <- "Reponse"
colnames(data_graph)[2] <- "Decompte"
# Ajout du nombre de repondants pour calculer le ratio
total_repondants <- data_visualisation[ data_visualisation[deuxieme_champ] != "" ,index_deuxieme_champ] %>% length()
data_graph[,3] <- total_repondants %>% as.numeric()
colnames(data_graph)[3] <- 'Total_repondants'
data_graph[,4] <- data_graph[,2] / data_graph[,3]
colnames(data_graph)[4] <- 'Ratio'
# Tri de donnees du plus petit au plus grand
if( tri_asc == TRUE){
aide_data_graph <- data_graph %>% arrange(Ratio) %>% select(Reponse) %>% unique()
data_graph <- data_graph %>% mutate(Reponse=factor(Reponse, levels=aide_data_graph[["Reponse"]]))
} else if(tri_asc == "CUSTOM" & is.vector(tri_aide) == TRUE){
data_graph <- data_graph %>% mutate(Reponse=factor(Reponse, levels=tri_aide))
}
#
# Generation du graphique
#
graph_question <- ggplot(data=data_graph, aes(x=Reponse, y=Ratio)) +
geom_bar(stat="identity", width = 0.5, fill = color_fill) +
# ggtitle(titre) +
theme_minimal() +
coord_flip() +
theme(axis.text.x = element_text(angle = 0, hjust = 1, vjust=1)) +
theme( axis.title.x = element_blank(), axis.title.y = element_blank() ) +
scale_y_continuous(labels=percent)
# Retourner le graphiquea la fin
return(graph_question )
}
# Graph1 - Pour le motif
nom_question <- "Quel_est_votre_motif_de_visite"
deuxieme_champ <- "Quelle_est_votre_satisfaction"
graph1 <- visualisation_barres_avec_2eme_champ_filtre(data_visualisation, nom_question, deuxieme_champ) %>% ggplotly() %>% config(modeBarButtonsToRemove = c("lasso2d", "pan2d", "zoom2d"))
# FONCTION pour barres empilees
visualisation_barres_empiles <- function(data_visualisation, nom_question, champ_remplissage, libelle_axe = TRUE, color_fill = c("#28B463", "#A9DFBF","#F9EBEA", "#F1948A","#CB4335")){
# Formatter le nom de question pour qu il corresponde a celui de la table
nom_question <- formatter_texte(nom_question)
# Préparation du tableau pour visualisation avec 1 data frame par question et transposition du decompte des valeurs en ligne
# Recuperation des colonnes a utiliser
index_colonne_question <- which(colnames(data_visualisation) == nom_question)
index_champ_remplissage <- which(colnames(data_visualisation) == champ_remplissage)
data_graph <- data_visualisation[] %>% filter(.data[[nom_question]] != "" & .data[[champ_remplissage]] != "") %>% count(.data[[nom_question]], .data[[champ_remplissage]])
colnames(data_graph)[1] <- "Reponse"
colnames(data_graph)[2] <- "Note"
colnames(data_graph)[3] <- "Decompte"
# Ajout du nombre de repondants pour calculer le ratio
total_repondants <- data_visualisation[ data_visualisation[champ_remplissage] != "" ,index_champ_remplissage] %>% length()
data_graph[,4] <- total_repondants %>% as.numeric()
colnames(data_graph)[4] <- 'Total_repondants'
data_graph[,5] <- data_graph[,3] / data_graph[,4]
colnames(data_graph)[5] <- 'Ratio'
# Ordre de donnees du plus petit au plus grand
aide_data_reponse <- data_graph %>% group_by(Reponse) %>% summarise(Ratio=sum(Ratio)) %>% arrange(Ratio) %>% select(Reponse)
data_graph <- data_graph %>% mutate(Reponses=factor(Reponse, levels=aide_data_reponse[["Reponse"]]))
# Ordre des libellés de satisfaction (color_fill)
aide_data_note <- data_graph %>% select(Note) %>% unique() %>% arrange(desc(Note))
data_graph <- data_graph %>% mutate(Notes=factor(Note, levels=aide_data_note[["Note"]]))
#
# Generation du graphique
#
if(libelle_axe == TRUE){
graph_question <- ggplot(data=data_graph, aes(x=Reponses, y=Decompte, fill=Notes)) +
geom_bar(position="fill", stat="identity") +
theme_minimal() +
coord_flip() +
theme(axis.text.y = element_text(angle = 0, hjust = 1, vjust=1), legend.position = "top", legend.title=element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()) +
scale_y_continuous(labels=percent) +
scale_fill_manual(values=color_fill)
} else {
graph_question <- ggplot(data=data_graph, aes(x=Reponses, y=Decompte, fill=Notes)) +
geom_bar(position="fill", stat="identity") +
theme_minimal() +
coord_flip() +
theme(axis.text.y = element_blank(), legend.position = "top", legend.title=element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()) +
scale_y_continuous(labels=percent) +
scale_fill_manual(values=color_fill)
}
# Retourner le graphique a la fin
return(graph_question)
}
# FONCTION pour gerer la legende avec plotly
reverse_legend_labels <- function(plotly_plot) {
n_labels <- length(plotly_plot$x$data)
plotly_plot$x$data[1:n_labels] <- plotly_plot$x$data[n_labels:1]
plotly_plot
}
# Graph2 - Pour le motif détaillé par la satisfaction
nom_question <- "Quel_est_votre_motif_de_visite"
champ_remplissage <- "Quelle_est_votre_satisfaction"
graph2 <- visualisation_barres_empiles(data_visualisation, nom_question, champ_remplissage, libelle_axe=FALSE) %>% ggplotly() %>% reverse_legend_labels() %>% layout(legend = list(orientation = "h", x = 0, y = 1.2)) %>% config(modeBarButtonsToRemove = c("lasso2d", "pan2d", "zoom2d"))
# Affichage dans une grille pour que les graphiques soient cote a cote
subplot(graph1, graph2, widths = c(0.2, 0.8)) %>% layout(autosize = FALSE, width = 900)
#
# 3eme partie
#
# Tableau de la note moyenne par motif
glue("Note moyenne par motif de visite :")
# Transformation des reponses de satisfaction de texte en numerique
notes <- data_visualisation[["Quelle_est_votre_satisfaction"]] %>% str_sub(1,1) %>% as.numeric()
# Calcul des notes moyenne et tri desc
data_tableau <- data_visualisation %>% mutate(notes=notes) %>% filter(is.na(notes) == FALSE) %>% group_by(Quel_est_votre_motif_de_visite) %>% summarise(note_moyenne = mean(notes)) %>% arrange(desc(note_moyenne))
# Affichage du tableau avec les donnees
knitr::kable(data_tableau, align=rep('c', 3))
```
***
## FIN du rapport
Et pour générer ce document HTML de manière dynamique avec du code R, il s’agit de faire appel à ce code qui génère un fichier .md à partir du fichier .Rmd (via knit), puis le fichier HTML est généré à partir du fichier .md :
require(knitr)
require(markdown)
require(rmarkdown)
knit('monfichier.Rmd', 'monfichier.md')
markdownToHTML('monfichier.md', 'monfichier.html')
Pour + d’infos :