Thomas Denecker & Claire Toffano-Nioche
Session 6
24/05/2019
Novembre
Janvier
Février
Mars
Avril
Mai
Juin
Juillet
...
26
25
22
29
26
24
21
à définir
...
Proposition le 05 juilletÂ
LoveR
Simplicité de l'exploration
Â
Simplicité du paramétrageÂ
Â
Reproductibilité de la visualisation
Rappel R
Â
Le package ShinyÂ
  - Import d'un fichier
  - Affichage d'un tableau
  - Connection tableau <-> graphique
  - Graphique R de base avec paramétrage
Teasing de la puissance de R
 - Exploration des données : dplyr Â
 - Réalisation de graphiques : plotly, google chart, ggplot2
 - Lecture de fichiers spéciaux : fasta, fastq, excel
 - Croisement de jeux de données : upset R
Gratuit et participatif
Fonctions statistiques et graphiques avancées
 - Calculs sur des variables
 - Tests statistiques
 - Représentations graphiques
Librairies complémentaires
 - Bio-informatique
 - Data-mining
 - Bases de données, ...
Interfaces possibles avec d'autres langages
 - Shell
 - Python, ...
Des comptes à suivre sur Twitter (#rstats)
Des événements R
Gratuit
Simple d'utilisation
Paramétrable
Un gain de temps considérable
Â
Méthode 1 ( l'ordre est important ! )
Â
1-Â Installer R (depuis le CRAN) Â
Â
2- Installation de RstudioÂ
https://www.rstudio.com/products/rstudio/download/
Â
Méthode 2
Â
Docker !! https://www.rocker-project.org/images/
install.packages("shiny")
library(shiny)
Package R qui facilite la création d'applications web interactives directement à partir de RÂ
Â
Fonctions traduisent du R en HTML
Â
Â
Installation de Shiny
h1(‘Un titre’)
<h1>Un titre</h1>
Reproductibilité de la visualisation
Â
Reproductibilité de l'analyse (création d'un rapport)
Â
Simplifier l'exploration des résultats par l’interaction
Â
Changer des paramètres sans entrer dans le script
Â
Partager plus facilement son projet pour des non programmeurs (ouverture du projet au monde)
Â
Â
Pubmed (recherche shiny app)
Pour un package proposé en 2013 !
(si vous savez parler R)
Â
Et des connaissances en HTML, CSS et JS ?
Pas indispensables mais utiles pour du design fin et certains cas d'interactions
Â
UI
Entrées d'informations
(boutons, fichiers, ...)
Â
Affichage de sorties
(graphiques, textes, ...)
Traitement des entrées
(lecture des fichiers, ...)
Â
Création de sorties
(créations d'un plot)
input
output
Server
Interface utilisateur visible sur la page web
"Zone de travail" : calculs, préparation des données, ...
Création d'une petite application
Texte
Thomas DENECKER
Une application plus complexe ... mais pas infaisable pour des débutants de Shiny !Â
Â
Le code est à 100% disponible !
https://github.com/thomasdenecker/FAIR_Bioinfo/blob/master/R-code/app.R
Â
De nombreuses similitudes !
évidemment !Â
Dataset :Â IRIS (mesures sur des fleurs)
Source : https://archive.ics.uci.edu/ml/datasets/iris Â
Le tableau est composé de 5 colonnes :
 - la longueur des sépales
 - la largeur des sépales
 - la longueur des pétales
 - la largeur des pétales
 - l’espèce de fleurs
Le tableau est disponible ici :Â
https://github.com/bioinfo-fr/bioinfo-fr_Shiny/blob/master/datasetIris.txtÂ
Toutes disponibles sur le CRAN
Bonus : anylib est fonction qui installe (si besoin) et charge les librairies
install.packages("anyLib")
anyLib::anyLib(c("shiny", "shinydashboard", "shinyWidgets", "DT", "plotly", "ggplot2", "googleVis", "colourpicker"))
Création de l'application : Shiny, Shinydashboard
Entrées avancées : shinyWidgets, colourpicker
Création de graphiques : plotly, ggplot2, googleVis
Tableau dynamique : DT
Â
Utilisation du package Shinydashboard
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody()
)
server <- function(input, output) { }
shinyApp(ui, server)
Dans Rstudio
Dans un terminal (dans le dossier avec le fichier app.R
R -e "shiny::runApp('R-code', port=4444)"
Sauvegarder : app.R (et bien sûr versionner ! )
le nom de fichier n'est pas renseigné car app.R est le nom par défaut (comme Snakefile, dockerfile, ...)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="application/shiny-singletons"></script>
<script type="application/html-dependencies">json2[2014.02.04];jquery[1.12.4];shiny[1.3.0];font-awesome[5.3.1];bootstrap[3.3.7];AdminLTE[2.0.6];shinydashboard[0.7.1]</script>
<script src="shared/json2-min.js"></script>
<script src="shared/jquery.min.js"></script>
<link href="shared/shiny.css" rel="stylesheet" />
<script src="shared/shiny.min.js"></script>
<link href="font-awesome-5.3.1/css/all.min.css" rel="stylesheet" />
<link href="font-awesome-5.3.1/css/v4-shims.min.css" rel="stylesheet" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="shared/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="shared/bootstrap/js/bootstrap.min.js"></script>
<script src="shared/bootstrap/shim/html5shiv.min.js"></script>
<script src="shared/bootstrap/shim/respond.min.js"></script>
<link href="AdminLTE-2.0.6/AdminLTE.min.css" rel="stylesheet" />
<link href="AdminLTE-2.0.6/_all-skins.min.css" rel="stylesheet" />
<script src="AdminLTE-2.0.6/app.min.js"></script>
<link href="shinydashboard-0.7.1/shinydashboard.css" rel="stylesheet" />
<script src="shinydashboard-0.7.1/shinydashboard.min.js"></script>
</head>
<body class="skin-blue" style="min-height: 611px;">
<div class="wrapper">
<header class="main-header">
<span class="logo"></span>
<nav class="navbar navbar-static-top" role="navigation">
<span style="display:none;">
<i class="fa fa-bars"></i>
</span>
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav"></ul>
</div>
</nav>
</header>
<aside id="sidebarCollapsed" class="main-sidebar" data-collapsed="false">
<section id="sidebarItemExpanded" class="sidebar"></section>
</aside>
<div class="content-wrapper">
<section class="content"></section>
</div>
</div>
</body>
</html>
Zone principale
(grise)
Zone
de menu
(noire)
Titre
Zone de notifications
ui <- dashboardPage(
dashboardHeader(title = "bioinfo-fr"),
dashboardSidebar( ),
dashboardBody( )
)
ui <- dashboardPage(
dashboardHeader(title = "bioinfo-fr"),
dashboardSidebar(
sidebarMenu(
menuItem("Lecture des données", tabName = "readData", icon = icon("readme")),
menuItem("Visualisation des données", tabName = "visualization", icon = icon("poll"))
)
),
dashboardBody(
tabItems(
# Read data
tabItem(tabName = "readData",
h1("Lecture des données")
),
# visualization
tabItem(tabName = "visualization",
h1("Visualisation des données")
)
)
)
)
Zone noire
Zone grise
Les icones sont disponibles ici : https://fontawesome.com/
Paramétrage de la lecture (nom de colonnes, séparateur, guillemets, ...)
Prévisualisation de la lectureÂ
Â
Zone d'import
[...]
dashboardBody(
tabItems(
# Read data
tabItem(tabName = "readData",
h1("Lecture des données"),
fileInput("dataFile",label = NULL,
buttonLabel = "Browse...",
placeholder = "No file selected")
),
# visualization
tabItem(tabName = "visualization",
h1("Visualisation des données")
)
)
)
[...]
 3 paramètres de lecture :
 - Type de séparateurÂ
 - Type de guillemets
 - Nom de colonnes (présent ou non)
Â
Utilisation de radio buttons (5 arguments) :
 - id : identifiant
 - label : titre du groupe de radio buttonsÂ
 - choices : choix disponiblesÂ
 - selected : choix sélectionné
 - inline = T : alignement des radio buttons
Â
[…]
tabItem(tabName = "readData",
h1("Lecture des données"),
fileInput("dataFile",label = NULL,
buttonLabel = "Browse...",
placeholder = "No file selected"),
h3("Parameters"),
# Input: Checkbox if file has header
radioButtons(id = "header",
label = "Header",
choices = c("Yes" = TRUE,
"No" = FALSE),
selected = TRUE, inline=T),
# Input: Select separator ----
radioButtons(id = "sep",
label = "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = "\t", inline=T),
# Input: Select quotes ----
radioButtons(id = "quote",
label= "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = "", inline=T)
),
[…]
Nous devons travailler dans l'UI et dans le serveurÂ
UI
Entrées d'informations
(boutons, fichiers, ...)
Â
Affichage de sorties
(graphiques, textes, ...)
Traitement des entrées
(lecture des fichiers, ...)
Â
Création de sorties
(créations d'un plot)
input
output
Server
Interface utilisateur visible sur la page web
"Zone de travail" : calculs, préparation des données, ...
Nous devons travailler dans l'UI et dans le serveurÂ
UI
Fichier
Â
Â
Affichage du tableauÂ
Lecture du fichier
Â
Â
Création d'un affichage de tableau
input
output
Server
tabItems(
# Read data
tabItem(tabName = "readData",
h1("Lecture des données"),
fileInput("dataFile",label = NULL,
buttonLabel = "Browse...",
placeholder = "No file selected"),
h3("Parameters"),
[...]
# Input: Select quotes ----
radioButtons(inputId = "quote",
label= "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = "", inline=T),
h3("File preview"),
dataTableOutput(outputId = "preview")
),
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
[...]
)
server <- function(input, output) {
output$preview <- renderDataTable({
req(input$dataFile)
df <- read.csv(input$dataFile$datapath,
header = as.logical(input$header),
sep = input$sep,
quote = input$quote,
nrows=10
)
}, options = list(scrollX = TRUE , dom = 't'))
}
shinyApp(ui, server)
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
[...]
)
server <- function(input, output) {
output$preview <- renderDataTable({
req(input$dataFile)
df <- read.csv(input$dataFile$datapath,
header = as.logical(input$header),
sep = input$sep,
quote = input$quote,
nrows=10
)
}, options = list(scrollX = TRUE , dom = 't'))
}
shinyApp(ui, server)
récupération du contenu du radio button header
Ne travaille que si un fichier est renseigné
Création d'un rendu tableau
Localisation du rendu
Mettre sur une même ligne les paramètres et la pré-visualisation : Boostrap
fluidRow(
column(3,
h3("Parameters"),
[...]
# Input: Select quotes ----
radioButtons(inputId = "quote",
label= "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = "", inline=T)
),
column(9,
h3("File preview"),
dataTableOutput(outputId = "preview")
)
)
12 colonnes dans une ligne
Bouton qui lance l'analyse après la lecture du fichier
[...]
actionButton(inputId = "actBtnVisualisation", label = "Visualisation",icon = icon("play") )
[...]
Coté UI
data = reactiveValues()
observeEvent(input$actBtnVisualisation, {
data$table = read.csv(input$dataFile$datapath,
header = as.logical(input$header),
sep = input$sep,
quote = input$quote,
nrows=10)
})
Coté Server
Variable spéciale qui relance toutes les fonctions qui l'utilisent en cas de changements
observeEvent(input$actBtnVisualisation, {
data$table = read.csv(input$dataFile$datapath,
header = as.logical(input$header),
sep = input$sep,
quote = input$quote,
nrows=10)
sendSweetAlert(
session = session,
title = "Done !",
text = "Le fichier a bien été lu !",
type = "success"
)
updateTabItems(session, "tabs", selected = "visualization")
})
Coté Server
Changement de page après lecture
Utilisation du package DT : très performant et communication parfaite avec Shiny
tabItem(tabName = "visualization",
h1("Visualisation des données"),
h2("Exploration du tableau"),
dataTableOutput('dataTable')
)
Coté UI
output$dataTable = DT::renderDataTable(data$table)
Coté Server
output$dataTable = DT::renderDataTable({
datatable(data$table, filter = 'top') %>%
formatStyle('Sepal.Length',
background = styleColorBar(data$table$Sepal.Length, 'lightcoral'),
backgroundSize = '100% 90%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center'
) %>%
formatStyle(
'Sepal.Width',
backgroundColor = styleInterval(c(3,4), c('white', 'red', "firebrick")),
color = styleInterval(c(3,4), c('black', 'white', "white"))
) %>%
formatStyle(
'Petal.Length',
background = styleColorBar(data$table$Petal.Length, 'lightcoral'),
backgroundSize = '100% 90%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center'
) %>%
formatStyle(
'Petal.Width',
backgroundColor = styleInterval(c(1,2), c('white', 'red', "firebrick")),
color = styleInterval(c(1,2), c('black', 'white', "white"))
) %>%
formatStyle(
'Species',
backgroundColor = styleEqual(
unique(data$table$Species), c('lightblue', 'lightgreen', 'lavender')
)
)
})
Filtres
Histogrammes
Colorations conditionnelles
Zone de recherche
Dans l'articleÂ
 - des graphiques statiques
    - un plot de base avec R
    - un graphique avec ggplot2
 - des graphiques dynamiques
    - Avec plotly
    - Avec google
Â
Nous allons voir ici un plot de base avec paramétrage
Â
Même philosophie pour les autres
tabItem(tabName = "visualization",
h1("Visualisation des données"),
h2("Exploration du tableau"),
dataTableOutput('dataTable'),
h2("Graphiques"),
fluidRow(
column(3,plotOutput("plotAvecR") )
)
)
Coté UI
output$plotAvecR <- renderPlot({
plot(data$table$Petal.Length,data$table$Sepal.Length,
main = "Sepal length vs Petal length (R)",
ylab = "Sepal length",
xlab = "Petal length")
})
Coté Server
tabItem(tabName = "visualization",
h1("Visualisation des données"),
h2("Exploration du tableau"),
dataTableOutput('dataTable'),
h2("Graphiques"),
fluidRow(
column(3,plotOutput("plotAvecR") )
)
)
Coté UI
output$plotAvecR <- renderPlot({
plot(data$table$Petal.Length,data$table$Sepal.Length,
main = "Sepal length vs Petal length (R)",
ylab = "Sepal length",
xlab = "Petal length")
})
Coté Server
Localisation dans l'UI
Création d'un rendu plot
Utilisation de la réactive value
Présence de filtres dans le tableauÂ
Idée : N'utiliser que les données sélectionnées dans les filtres pour la représentation graphiqueÂ
output$plotAvecR <- renderPlot({
if (!is.null(data$table)) {
plot(data$table$Petal.Length[input$dataTable_rows_all],
data$table$Sepal.Length[input$dataTable_rows_all],
main = "Sepal length vs Petal length (R)",
ylab = "Sepal length",
xlab = "Petal length")
} else {
NULL
}
})
if (!is.null(data$table)) : pas d'affichage si nous n'avons pas lu de tableau
output$plotAvecR <- renderPlot({
if (!is.null(data$table)) {
plot(data$table$Petal.Length[input$dataTable_rows_all],
data$table$Sepal.Length[input$dataTable_rows_all],
main = "Sepal length vs Petal length (R)",
ylab = "Sepal length",
xlab = "Petal length")
} else {
NULL
}
})
Â
Â
Â
data$table$Petal.Length[input$dataTable_rows_all]
Â
Dans la variable réactive, nous souhaitons la table
Nous récupérons la colonne Petal.length
Nous récupérons les positions de toutes les lignes filtrées dans le tableauÂ
 1- Changement de la couleur des points
 2- Changement de la taille des points
 3- Changement du type de points
 4- Changement du titre
Â
Un peu d'organisation : le graphe et les paramètres sur la même ligne
fluidRow(
column(4, plotOutput("plotAvecR")),
column(4,
# Code paramètre 1
# Code paramètre 2
),
column(4,
# Code paramètre 3
# Code paramètre 4
)
),
 1- Changement de la couleur des points
colour picker (boîte de couleurs)
 2- Changement de la taille des points
slider
Â
 3- Changement du type de point
selectinput
Â
 4- Changement du titre
textinput
fluidRow(
column(4, plotOutput("plotAvecR")),
column(4,
colourpicker::colourInput("colR", "Couleur graphique R", "black",allowTransparent = T),
sliderInput("cex", "Taille",
min = 0.5, max = 3,
value = 1,step = 0.2
)),
column(4,
selectInput(inputId = "pch", choices = 1:20, label = "Type de points",selected = 1),
textInput("title", "Titre", "Sepal length vs Petal length (R)") )
),
1
2
3
4
1
2
3
4
plot(data$table$Petal.Length[input$dataTable_rows_all],
data$table$Sepal.Length[input$dataTable_rows_all],
main = input$title,
ylab = "Sepal length",
xlab = "Petal length",
pch = as.numeric(input$pch),
col = input$colR,
cex = input$cex)
Et voilà !
Il faudrait ajouter les versions des packages utilisés !
Â
Exemple de l'appli FAIR_bioinfo
De nombreux packages sont disponibles !
Â
Pour faciliter l'exploration d'un tableau : dplyr
Pour faire de plus beaux graphes : ggplot2, plotly,...
Lire des fichiers spéciaux
Â
Â
Avant
Après
dataExtract = data[, c("col1", "col5", "col6"]
dataExtract = dataExtract[which(dataExtract$col1 > 10), ]
col = NULL
for(i in dataExtract$col5){
if(i < 10) {
col = c(col, "red")
} else if (i < 15 ) {
col = c(col, "orange")
} else if (i < 20 ) {
col = c(col, "green")
} else {
col = c(col, "forestgreen")
}
}
dataExtract = cbind(dataExtract , col)
dataExtract = data %>%
select(col1, col5, col6) %>%
filter(col1 > 10) %>%
mutate(col= case_when(col5 < 10 ~ "red",
col5 < 15 ~ "orange",
col5 < 10 ~ "green",
TRUE ~ "forestgreen"))
Plotly
GoogleVis
Fasta
librairie : seqinrÂ
Fonction : read.fasta( )
Â
Fastq
librairie : Shortread (bioconductor)
Fonction : readFastq( )
Â
Excel
librairie : xlsx
Fonction : read.xlsx( )
...
Avant
Après
Avant
Après
Â
Reproductibilité de l'exploration des résultats
- Simplicité de paramétrage
- Simplicité de partageÂ
- Interaction avec les résultats
- Portable
Â
Â
R est le meilleur langage du monde    (ou presque!)
Session 7Â - Les notebooks
 - Rmarkdown
 - Jupyter / Jupyterlab
 - Mise en ligne avec Binder
 - Docker Jupyter
 - Générer le notebook de l'appli (simple) shiny
Â
 Session 8 - Les outils de Github
 - Github pages
 - Intégration continue
 - Zenodo
 - Release
 - Vos projets : discussion ouverte
Ajouter une page à l'application vue aujourd'hui et mettre la version des packagesÂ
Changer le jeu de données et ajouter des graphiques (corrélation entre 2 réplicats ?)
Bon courage !
RDV sur Slack en cas de problème