Chapitre 3 Quelques outils de visualisation dynamique/interactive

Tout comme leaflet pour les cartes, il existe de nombreux outils R dédiés à la visualisation interactive. Nous en présentons quelques uns dans cette partie.

3.1 Représentations classiques avec rAmCharts et plotly

Le package rAmCharts est très utile pour donner un caractère interactif à des représentations graphiques standards (nuages de points, séries temporelles, histogrammes…). Ce package a été fait dans l’esprit d’utiliser les fonctions graphiques de R en utilisant le préfixe am. La syntaxe est très proche de celle des fonctions graphiques standards. On a par exemple :

library(rAmCharts)
amHist(iris$Petal.Length)
amPlot(iris, col = colnames(iris)[1:2], type = c("l", "st"), 
       zoom = TRUE, legend = TRUE)
amBoxplot(iris)

plotly permet de faire des choses semblables avec avec une syntaxe spécifique. Les commandes plotly se décomposent essentiellement en 3 parties :

  • le type de représentation graphique (plot_ly}) ;
  • les ajouts que l’on souhaite effectuer (add_trace) ;
  • la gestion de la fenêtre graphique (axes, titres…) (layout).

On trouvera un descriptif complet de ces 3 composantes ici. On propose de tracer un nuage de points en dimension 2 et d’y ajouter la droite de régression. On commence par générer le nuage et ajuster le modèle linéaire :

library(plotly)
n <- 100
X <- runif(n,-5,5)
Y <- 2+3*X+rnorm(n,0,1)
D <- data.frame(X,Y)
model <- lm(Y~X,data=D)

On effectue maintenant le tracé

D %>% plot_ly(x=~X,y=~Y) %>%
  add_markers(type="scatter",mode="markers",
              marker=list(color="red"),name="Nuage") %>%
  add_trace(y=fitted(model),type="scatter",mode='lines',
            name="Régression",line=list(color="blue")) %>% 
  layout(title="Régression",xaxis=list(title="abscisse"),
         yaxis=list(title="ordonnées"))

Contrairement à ggplot, plotly permet de faire de la 3D. Par exemple

plot_ly(z = volcano, type = "surface")
plot_ly(z = volcano, type = "contour")

Il est possible de convertir des graphes ggplot au format plotly avec la fonction ggplotly :

p <- ggplot(iris)+aes(x=Species,y=Sepal.Length)+geom_boxplot()+theme_classic()
ggplotly(p)

Exercice 3.1 (Graphes basiques avec `rAmCharts` et `plotly`) Pour le jeu de données iris on effectuera les graphes suivants en rAmCharts et plotly.

  1. Nuage de points représentant les longueurs et largeurs de Sépales. On utilisera une couleur différente en fonction de l’espèce.

    amPlot(Sepal.Length~Sepal.Width,data=iris,col=iris$Species) 
    iris %>% plot_ly(x=~Sepal.Width,y=~Sepal.Length,color=~Species) %>%
      add_markers(type="scatter",mode="markers")
  2. Boxplot permettant de visualiser la distribution de la variable Petal.Length en fonction de l’espèce.

    amBoxplot(Petal.Length~Species,data=iris)
    iris %>% plot_ly(x=~Species,y=~Petal.Length) %>% add_boxplot()

3.2 Graphes pour visualiser des réseaux avec visNetwork

De nombreuses données peuvent être visualisées à l’aide d’un graphe, notamment lorsqu’il s’agit de représenter des connexions entre individus. Un individu est alors représentés par un noeud et les individus connectés sont reliés par des arêtes. Le package igraph propose une visualisation statique d’un réseau. Pour donner un caractère dynamique à ce type de représentation, on pourra utiliser le package visNetwork. Une représentation standard visNetwork s’effectue en spécifiant les nœuds et connexions d’un graphe, par exemple :

nodes <- data.frame(id = 1:15, label = paste("Id", 1:15),
                    group=sample(LETTERS[1:3], 15, replace = TRUE))
edges <- data.frame(from = trunc(runif(15)*(15-1))+1,to = trunc(runif(15)*(15-1))+1)
library(visNetwork)
visNetwork(nodes,edges)
visNetwork(nodes, edges) %>% visOptions(highlightNearest = TRUE)
visNetwork(nodes, edges) %>% visOptions(highlightNearest = TRUE,
                                        nodesIdSelection = TRUE)


visNetwork(nodes, edges) %>% visOptions(selectedBy = "group")

Exercice 3.2 (Interactions entre media) On considère un graphe qui représente des liens entre différents médias. Les données sont présentées ici et on peut les importer avec

nodes <- read.csv("data/Dataset1-Media-Example-NODES.csv", header=T, as.is=T)
links <- read.csv("data/Dataset1-Media-Example-EDGES.csv", header=T, as.is=T)
head(nodes)
   id               media media.type type.label
1 s01            NY Times          1  Newspaper
2 s02     Washington Post          1  Newspaper
3 s03 Wall Street Journal          1  Newspaper
4 s04           USA Today          1  Newspaper
5 s05            LA Times          1  Newspaper
6 s06       New York Post          1  Newspaper
  audience.size
1            20
2            25
3            30
4            32
5            20
6            50
head(links)
  from  to weight      type
1  s01 s02     10 hyperlink
2  s01 s02     12 hyperlink
3  s01 s03     22 hyperlink
4  s01 s04     21 hyperlink
5  s04 s11     22   mention
6  s05 s15     21   mention

L’objet nodes représente les noeuds du graphe et l’objets links les arêtes. On définit l’objet graphe avec

library(igraph)
media <- graph_from_data_frame(d=links, vertices=nodes, directed=T) 
V(media)$name <- nodes$media

et on peut le visualiser en faisant un plot de cet objet

plot(media)

  1. Visualiser ce graphe avec VisNetwork. On pourra utiliser la fonction toVisNetworkData.

    media.VN <- toVisNetworkData(media)
    visNetwork(nodes=media.VN$nodes,edges=media.VN$edges)
  2. Ajouter une option qui permette de sélectionner le type de media (Newspaper, TV ou Online).

    names(media.VN$nodes)[4] <- "labels"
    visNetwork(nodes=media.VN$nodes,edges=media.VN$edges) %>% 
      visOptions(selectedBy = "labels")


  3. Utiliser une couleur différente pour chaque type de media.

    Il suffit de donner le nom group à la variable type.label.

    media.VN1 <- media.VN
    names(media.VN1$nodes)[3] <- "group"
    visNetwork(nodes=media.VN1$nodes,edges=media.VN1$edges) %>% 
      visOptions(selectedBy = "labels")


  4. Faire des flèches d’épaisseur différente en fonction du poids (weight). On pourra également ajouter l’option visOptions(highlightNearest = TRUE).

    Il suffit de donner le nom value à la variable weight.

    names(media.VN1$edges)[3] <- "value"
    visNetwork(nodes=media.VN1$nodes,edges=media.VN1$edges) %>% 
      visOptions(selectedBy = "labels",highlightNearest = TRUE) 

3.3 Dashboard

Un tableau de bord permet de visualiser “facilement” et “rapidement” divers graphes et/ou résumés statistiques en lien avec une problématique donnée. Sur R le package flexdashboard permet de construire de tels tableaux de bord. On trouvera un descriptif précis de ce package à cette url : https://rmarkdown.rstudio.com/flexdashboard/. On utilisera cette documentation pour faire l’exercice suivant.

Exercice 3.3 (Dashboard pour modèles linéaires) On considère le jeu de données ozone.txt. Le problème est d’expliquer la concentration maximale en ozone quotidienne (variable maxO3) par d’autres variables météorologiques (températures et indicateurs de nébulosité relevés à différents moments de la journée…). On souhaite faire un tableau de bord qui permettra de :

  • visualiser les données : la base de données ainsi qu’un ou deux graphes descriptifs sur la variable à expliquer ;
  • visualiser les modèles linéaires simples : on choisit une variable explicative et on visualise le graphe de la régression ainsi que le modèle ;
  • visualiser le modèle linéaire complet : on affiche le résultat de la régression avec toutes les variables et on représente le graphe des résidus ;
  • choisir les variables explicatives.
  1. Avant de réaliser le dashboard, on propose d’écrire quelques commandes pour calculer les différentes sorties :
    1. On considère uniquement les variables quantitatives du jeu de données. Visualiser les corrélations entre ces variables à l’aide de la fonction corrplot du package corrplot.

      df <- read.table("data/ozone.txt")
      cc <- cor(df[,1:11])
      mat.cor <- corrplot::corrplot(cc)

    2. Représenter l’histogramme de la variable maxO3, on fera le graphe ggplot et rAmCharts et plotly (en utilisant ggplotly par exemple).

      gg.H <- ggplot(df)+aes(x=maxO3)+geom_histogram(bins = 10)
      am.H <- amHist(df$maxO3)
      pl.H <- ggplotly(gg.H)
    3. Construire le modèle linéaire permettant d’expliquer maxO3 par les autres variables. Calculer les résidus studentisés (rstudent) et visualiser ces résidus en fonction de la variable maxO3. Là encore on pourra ajouter un lisseur sur le graphe.

      mod <- lm(maxO3~.,data=df)
      res <- rstudent(mod)
      df1 <- data.frame(maxO3=df$maxO3,r.student=res)
      Ggg <- ggplot(df1)+aes(x=maxO3,y=res)+geom_point()+geom_smooth()
      Gggp <- ggplotly(Ggg)
  2. On peut maintenant passer au tableau de bord. On utilise le menu File -> Rmarkdown -> From Template -> Flex Dashboard.
    1. Construire un premier dashboard permettant de visualiser :

      • le jeu de données sur une colonne (on pourra utiliser la fonction datatable du package DT)
      • l’histogramme de la variable maxO3 ainsi que la matrice des corrélations entre les variables quantitatives.
    2. Ajouter un nouvel onglet qui permet de visualiser le summary du modèle linéaire complet. On pourra utiliser la fonction datatable du package DT. Indication : ce nouvel onglet peut se créer avec

      Name of the tab
      =====================================  
    3. Ajouter un nouvel onglet qui permet de visualiser un modèle linéaire simple avec la variable explicative de votre choix. On pourra afficher dans cet onglet le summary du modèle ainsi que le nuage de points et la droite de régression.

    4. Pour aller plus loin : ajouter un dernier onglet qui permette à l’utilisateur de choisir la variable explicative du modèle simple. Indications : on pourra utiliser les commandes Shiny

      • Choix de la variable
      radioButtons("variable1",
                         label="Choisir la variable explicative",
                         choices=names(df)[-1],
                         selected=list("T9"))
      • Mise à jour du résumé
      mod1 <- reactive({
        XX <- paste(input$variable1,collapse="+")
        form <- paste("maxO3~",XX,sep="") %>% formula()
        lm(form,data=df)
        })
      #Df correspond au jeu de données
      renderDataTable({
        mod.sum1 <- summary(mod1())$coefficients %>% round(3) %>% as.data.frame()
        DT::datatable(mod.sum1,options = list(dom = 't'))
      })
      • Mise à jour du graph interactif
      renderPlotly({
        (ggplot(df)+aes(x=!!as.name(input$variable1),y=maxO3)+
           geom_point()+geom_smooth(method="lm")) %>% ggplotly()
      })

      Enfin il ne faudra pas oublier d’ajouter

      runtime: shiny

      dans l’entête.

    5. Ajouter un dernier onglet permettant de choisir les variables explicatives dans le modèle linéaire. Là encore on pourra utiliser des commandes Shiny, par exemple

      checkboxGroupInput("variable",
                         label="Choisir la variable",
                         choices=names(df)[-1],
                         selected=list("T9"))

      Pour les variables choisies, on affichera dans ce nouvel onglet les coefficients du modèle linéaire ainsi que le graphe des résidus studentisés.

Le tableau de bord finalisé pourra ressembler à

Il est disponible à l’url https://lrouviere.shinyapps.io/dashboard/