Nous allons utiliser dans ce TP le package shinydashboard
(à installer donc), qui permet de créer des tableaux de bords (ou dashboard en anglais), à l’aide de la librairie shiny
.
Le data.frame
txhousing
du package ggplot2
contient les informations économiques mensuelles du Texas, pour différentes villes et sur la période 2000-2015.
city | year | month | sales | volume | median | listings | inventory | date |
---|---|---|---|---|---|---|---|---|
Abilene | 2000 | 1 | 72 | 5380000 | 71400 | 701 | 6.3 | 2000.000 |
Abilene | 2000 | 2 | 98 | 6505000 | 58700 | 746 | 6.6 | 2000.083 |
Abilene | 2000 | 3 | 130 | 9285000 | 58100 | 784 | 6.8 | 2000.167 |
Abilene | 2000 | 4 | 98 | 9730000 | 68600 | 785 | 6.9 | 2000.250 |
Abilene | 2000 | 5 | 141 | 10590000 | 67300 | 794 | 6.8 | 2000.333 |
Abilene | 2000 | 6 | 156 | 13910000 | 66900 | 780 | 6.6 | 2000.417 |
Nous allons commencer par créer la base de notre application. Ainsi, au lieu de créer une fluidPage()
comme nous l’avions fait précédemment, nous allons utiliser la fonction dashboardPage()
. Celle-ci prend au minimum trois arguments
dashboardHeader()
dashboardSidebar()
dashboardBody()
Elle peut aussi prendre deux autres paramètres optionnels :
title
)skin
, pouvant prendre les valeurs "blue"
, "black"
, "purple"
, "green"
, "red"
ou "yellow"
)Voici donc le contenu initial de notre nouvelle application (à mettre dans un nouveau répertoire donc).
ui.R
library(shiny)
library(shinydashboard)
shinyUI(dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(),
title = "TP 6",
skin = "yellow"
))
server.R
library(shiny)
library(shinydashboard)
shinyServer(function(input, output) {
})
Dans la partie en-tête, déclarée avec la fonction dashboardHeader()
, nous allons écrire d’une part le titre qui apparaîtra en haut à gauche de l’application, ainsi que les différents items qui vont appraître dans la barre de menu en haut.
Pour ajouter un titre au tableau de bord, il suffit de donner une valeur au paramètre title
de la fonction dashboardHeader()
. Commençons par lui donner le titre "TP 6"
, comme ci-dessous.
dashboardHeader(
title = "TP 6"
)
Il est possible d’ajouter d’autres éléments dans la barre de menu, que nous ne verrons pas ici.
La fonction box()
permet de déclarer une boîte, dans laquelle nous allons pouvoir intégrer des éléments de type input
ou output
. On pourra ensuite positionner ces boîtes librement avec des fonctions telles que fluidRow()
.
Nous allons d’abord créer une box()
qui contiendra l’évolution globale du volume des ventes (variable volume
). Pour cela, nous allons devoir faire un agrégat par date, bien évidemment.
Dans l’interface, nous ajoutons donc une box()
, avec un titre et une sortie de type graphique, nommée conso
. Dans la partie serveur, nous créons le graphique classiquement, dans un renderPlot()
.
ui.R
dashboardBody(
box(
title = "Volume des ventes",
plotOutput("conso")
)
)
server.R
output$conso <- renderPlot({
df = aggregate(volume ~ date, txhousing, sum)
ggplot(df, aes(date, volume)) + geom_line()
})
La fonction box()
peut prendre différents paramètres permettant de personnaliser l’affichage :
footer
: texte en pied de la boîtestatus
: statut de la boîte, définissant un aspect type (regarder l’aide de validStatuses
pour plus d’infos)solidHeader
: pour dire si le titre a une couleur de fond ou nonwidth
: largeur de la boîte (entre 1 et 12),On peut donc avoir une boîte personnalisée comme ci-dessous.
ui.R
box(
title = "Volume des ventes",
plotOutput("conso"),
footer = "Données provenant de txhousing",
status = "info",
solidHeader = TRUE,
width = 8
)
infoBox()
Ce type de boîte permet de donner une information particulière, courte. Voici comment l’intégrer dans l’interface.
ui.R
(à la suite de la première box()
)infoBox(
title = "Progression"
)
En plus du titre, nous pouvons bien évidemment mettre une valeur. On peut aussi personnaliser ces boîtes en changeant l’icône, le remplissage ou non et la couleur.
ui.R
infoBox(
title = "Progression",
value = "?",
subtitle = "Entre 2000 et 2015",
icon = icon("line-chart"),
fill = TRUE,
color = "light-blue"
)
valueBox()
C’est un autre type de boîte pour donner une information courte, comme nous l’avions vu avec le package flexdashboard
.
ui.R
(à la suite de l’infoBox()
)valueBox(
value = "?",
subtitle = "Volume totale des ventes"
)
Ici, nous pouvons la personnaliser, avec une icône et une couleur spécifiques.
ui.R
valueBox(
value = "?",
subtitle = "Volume totale des ventes",
icon = icon("usd"),
color = "light-blue"
)
tabBox()
On peut avoir un système d’onglets dans une box()
grâce à cette fonction. Celle-ci prend en premier paramètre le titre qui s’affichera en haut à droite par défaut. Un autre paramètre possible est la largeur. Ici, nous définissons une largeur de 4, pour que le tabBox()
se mette à la suite des deux autres boîtes (tester l’applciation en commentant cette ligne). Ensuite, chaque onglet est définié avec la fonction tabPanel()
. Celle-ci prend en paramètre le titre et une suite d’éléments (ici, du texte uniquement - nous modifierons cela par la suite).
ui.R
tabBox(
title = "Informations",
width = 4,
tabPanel(title = "Nombre", "Nombre de ventes"),
tabPanel(title = "Prix médian", "prix médian")
)
La fonction dashboardSidebar()
va nous permetter de déterminer le contenu de la partie gauche du tableau de bord, dédiée principalement aux différents choix que pourra faire l’utilisateur.
Dans ce type de tableau de bord, il est courant de soit vouloir toutes les villes, soit uniquement une ville spécifique. Pour cela, nous allons donc ajouter un selectInput()
, nommée ville
, qui permettra à l’utilisateur de choisir soit toutes les villes, soit une seule. Dans la liste des choix, nous devons donc créer un vecteur contenant toutes les valeurs de la variable city
, ainsi que la chaîne "Toutes les villes"
. Et dans le serveur, il va nous falloir tester le choix de l’utilisateur, et différencier le code à exécuter selon celui-ci.
Voici donc les éléments à ajouter à notre code précédent.
ui.R
(dans le dashboardSidebar()
)selectInput(
"ville",
"Choix de la ville",
c("Toutes les villes", unique(txhousing$city))
)
server.R
(à la place de la création de df
)if (input$ville == "Toutes les villes") {
df = aggregate(volume ~ date, txhousing, sum)
} else {
df = aggregate(volume ~ date,
subset(txhousing, city == input$ville),
sum)
}
input
(cette partie n’est pas spécifique à shinydashboard
)
Il est possible de créer un output
de type interface avec la fonction uiOutput()
. Ceci nous permet de créer une infoBox()
(ou une valueBox()
) en fonction des input
de l’utilisateur (ou autre chose). Pour créer le rendu, nous devrons utiliser la fonction renderUI()
.
Nous allons l’utiliser ici pour indiquer la progression en % du volume de ventes mensuels médians entre Janvier 2000 et Janvier 2015 pour la ville choisie.
Nous allons commencer par modifier l’interface pour intégrer un uiOutput()
. Et dans la partie serveur, nous allons pour le moment renvoyer la même ìnfoBox()
que précédemment.
ui.R
(à la place de l’ìnfoBox()
)uiOutput("progression")
server.R
(à la suite)output$progression <- renderUI({
valeur = 0
couleur = "light-blue"
infoBox(
title = "Progression",
value = valeur,
subtitle = "Entre 2000 et 2015",
icon = icon("line-chart"),
fill = TRUE,
color = couleur
)
})
Il nous faut maintenant calculer la progression entre Janvier 2000 et Janvier 2015 pour la ville choisie. Si l’utilisateur choisit toutes les villes, le calcul se fera pour toutes les villes. Nous allons donc ré-utiliser presque le même calcul, sauf que l’agrégat se fera sur l’année (year
).
Une fois la valeur calculée, nous allons choisir la couleur avec la règle suivante :
"red"
)"light-blue"
)supérieure à 350 : vert ("green"
)
server.R
output$progression <- renderUI({
if (input$ville == "Toutes les villes") {
med2000 = median(subset(txhousing, year == 2000)$volume, na.rm = T)
med2015 = median(subset(txhousing, year == 2015)$volume, na.rm = T)
} else {
med2000 = median(subset(txhousing, year == 2000 & city == input$ville)$volume,
na.rm = T)
med2015 = median(subset(txhousing, year == 2015 & city == input$ville)$volume,
na.rm = T)
}
valeur = round(med2015 / med2000 * 100, 2)
couleur = ifelse(valeur < 200, "red", ifelse(valeur < 350, "light-blue", "green"))
infoBox(
title = "Progression",
value = paste(valeur, "%"),
subtitle = "Entre 2000 et 2015",
icon = icon("line-chart"),
fill = TRUE,
color = couleur
)
})
Tester les trois premières villes pour voir la modification de l’infoBox()
.
Pour information, la ville de Terkaxana n’a aucune information pour 2000. La valeur obtenue est donc NA
. L’infoBox()
ne fonctionne donc pas pour celle-ci (avec une production d’erreur, non bloquante pour l’application).
Il est possible de donner la possibilité d’avoir plusieurs écrans (ou ensemble de graphique) dans le tableau de bords. Pour cela, nous allons définir un menu (avec plusieurs items) dans la partie sidebar
et définir le contenu de chaque item de ce menu dans le body
.
Le menu se déclare avec la fonction sidebarMenu()
, et les items du menu par des menuItem()
. On doit définir le texte à afficher et l’identifiant de l’item. On peut y ajouter des icônes pour personnaliser le menu. On peut aussi insérer un lien si on le souhaite.
ui.R
: dans la partie sidebar
, en dessous du selectInput()
sidebarMenu(
menuItem("Résumé", tabName = "resume", icon = icon("dashboard")),
menuItem("TOP", tabName = "top", icon = icon("thumbs-up")),
menuItem("Liste des icônes", icon = icon("font-awesome"), href = "http://fontawesome.io/icons/")
)
Dans la partie body
, nous devons définir le contenu de chaque item dans un tabItem()
dans lequel el premier paramètre est l’identifiant de l’item (cf tabName
de menuItem()
). Tous les items doivent être inclus dans un tabItems()
.
ui.R
: dans la partie body
tabItems(
tabItem(
"resume",
box(
title = "Volume des ventes",
plotOutput("conso"),
footer = "Données provenant de txhousing",
status = "info",
solidHeader = TRUE,
width = 8
),
uiOutput("progression"),
valueBox(
value = "?",
subtitle = "Volume totale des ventes",
icon = icon("usd"),
color = "light-blue"
),
tabBox(
title = "Informations",
width = 4,
tabPanel("Nombre", "Nombre de ventes"),
tabPanel("Prix médian", "prix médian")
)
),
tabItem(
"top"
)
)
infoBox()
pour vérifier que les valeurs ont pu être calculées pour 2000 et 2015
infoBox()
avec une icône de type warning
et de couleur rougevalueBox()
pour afficher le volume total des ventes pour la ville choisie (somme des ventes sur toute la période), avec une couleur en fonction des critères suivants :
tabBox()
déjà écrite les valeurs prévues sous forme de textOutput()
simple pour le moment
box()
avec le graphique pour en faire une tabBox()
contenant les éléments suivants :
aggregate()
et acast()
du package reshape2
)library(reshape2)
a = aggregate(volume ~ year + month, txhousing, sum)
b = acast(a, year ~ month, value.var = "volume")
c = b / 1000000
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2000 | 1619 | 2224 | 2926 | 2731 | 3363 | 3623 | 3257 | 3380 | 2732 | 2624 | 2418 | 2445 |
2001 | 1831 | 2356 | 3123 | 3033 | 3558 | 3917 | 3744 | 3686 | 2672 | 2538 | 2556 | 2790 |
2002 | 2176 | 2585 | 3103 | 3306 | 3879 | 3720 | 3801 | 3573 | 2927 | 2954 | 2610 | 3166 |
2003 | 2184 | 2511 | 3249 | 3296 | 3869 | 4261 | 4448 | 4329 | 3674 | 3417 | 2778 | 3658 |
2004 | 2282 | 2911 | 3933 | 4243 | 4512 | 5262 | 4887 | 4736 | 3913 | 3671 | 3451 | 4113 |
2005 | 2619 | 3326 | 4589 | 4717 | 5442 | 6095 | 5712 | 5904 | 4730 | 4438 | 4264 | 4698 |
2006 | 3216 | 4112 | 5661 | 5147 | 6614 | 7438 | 6390 | 6613 | 5223 | 4949 | 4699 | 5177 |
2007 | 3581 | 4321 | 5780 | 5630 | 6739 | 7127 | 6590 | 6768 | 4527 | 4582 | 4375 | 4373 |
2008 | 3145 | 3972 | 4754 | 5024 | 5779 | 6068 | 5818 | 5515 | 4061 | 3784 | 2738 | 3542 |
2009 | 2173 | 2861 | 3623 | 3725 | 4429 | 5310 | 5372 | 4671 | 4237 | 4291 | 3952 | 3808 |
2010 | 2251 | 2921 | 4441 | 4991 | 5303 | 5424 | 4227 | 4186 | 3614 | 3344 | 3273 | 3877 |
2011 | 2452 | 2854 | 4128 | 4264 | 4786 | 5477 | 4812 | 5177 | 4180 | 3616 | 3465 | 3997 |
2012 | 2648 | 3414 | 4679 | 5039 | 6181 | 6531 | 6106 | 6330 | 4797 | 4999 | 4617 | 4911 |
2013 | 3505 | 4153 | 5934 | 6970 | 8274 | 8098 | 8473 | 8166 | 6364 | 5935 | 5193 | 5893 |
2014 | 3948 | 4961 | 6426 | 7201 | 8422 | 9178 | 8911 | 8470 | 7268 | 7146 | 5679 | 7152 |
2015 | 4445 | 5255 | 7417 | 7903 | 8895 | 10095 | 10109 | NA | NA | NA | NA | NA |
"TOP"
, les différents TOP suivants (chacun dans une box()
) :