Un outil graphique interactif adapté aux plateformes mobiles avec highcharter

Marwa Essid et Maxime Tessier

2018-05-10



1 Introduction

Le package highcharter de R est en fait un « wrapper », c’est-à-dire une fonction qui appelle une autre fonction, de l’outil graphique Highcharts. Highcharts a été lancé en 2009 suite à sa création par Torstein Hønsi. Cet outil est programmé en JavaScript et il est maintenu par la compagnie Highsoft. Il permet de créer etd’intégrer des graphiques interactifs ou statiques à des pages et des applications web.

Il est compatible avec les différents navigateurs et même adapté pour les mobiles. Il est possible d’interagir avec les graphiques à l’aide des commandes tactiles des téléphones intelligents. Les graphiques provenant de Highcharts sont créés en formats SVG et VML. Ces formats d’images sont en fait des images dites vectorielles, elles sont donc facilement manipulables et ne perdent pas de qualité visuelle lorsque leurs dimensions sont modifiées, par exemple le fait d’agrandir l’image ne la rend pas floue comme avec d’autres formats.

Highcharts inclut aussi deux autres modules produits et maintenus par Highsoft. Le premier module est Highstock qui permet de produire des graphiques d’évolution temporelle et d’autres pour le suivi des actions. Le deuxième module est Highmaps qui permet de représenter des données sur des cartes.

Le package highcharter est pour sa part maintenu par Joshua Kunst. Il permet d’utiliser une grande partie des fonctions disponibles de Highcharts. Une multitude de types de graphiques est donc disponible, comme les histogrammes, les courbes, les diagrammes en secteurs, les graphiques en bâtons, les graphiques en 3D et bien d’autres. La prochaine section présentera un aperçu ainsi qu’un guide de base sur l’utilisation du package highcharter.

1.1 Installation du package highcharter

#Installation de highcharter
install.packages("highcharter", repos = "http://cran.us.r-project.org")
#Chargement du package dans la session R
library(highcharter)

2 Fonctionnalités du package highcharter

Cette section est dédiée à présenter les principales fonctions du package highcharter. Pour tous les exemples qui vont suivre, le jeu de données quakes du package datasets sera utilisé. Ce jeu de données contient des données sur des séisme dans les Îles Fidji depuis 1964. Les variables disponibles dans ce jeu de données sont: lat qui correspond à la latitude, long qui correspond à la longitude, depth qui correspond à la profondeur du séisme en kilomètres, mag qui correspond à la magnitude du séisme selon l’échelle de Richter et stations qui donne le nombre de stations qui ont détectées le séisme. Nous ajoutons 2 autres variables au jeu de données pour le bien des démonstrations qui suivront: la variable magfactor qui transforme la variable mag en facteurs selon l’entier de la valeur sur l’échelle de Richter et region qui est également un facteur qui prend la valeur 'Est' ou 'Ouest' selon l’emplacement du séisme s’il est plus à l’est ou à l’ouest.

# Création d'un facteur à partir de la variable mag
quakes$magFactor <- factor(floor(quakes$mag))

# Création d'un deuxième facteur à partir des variables lat et long (coordonnées géographiques)
quakes$region <- factor(quakes$long >= 175, labels = c("Ouest", "Est"))

#Type de données du jeu de données quakes
str(quakes)
## 'data.frame':    1000 obs. of  7 variables:
##  $ lat      : num  -20.4 -20.6 -26 -18 -20.4 ...
##  $ long     : num  182 181 184 182 182 ...
##  $ depth    : int  562 650 42 626 649 195 82 194 211 622 ...
##  $ mag      : num  4.8 4.2 5.4 4.1 4 4 4.8 4.4 4.7 4.3 ...
##  $ stations : int  41 15 43 19 11 12 43 15 35 19 ...
##  $ magFactor: Factor w/ 3 levels "4","5","6": 1 1 2 1 1 1 1 1 1 1 ...
##  $ region   : Factor w/ 2 levels "Ouest","Est": 2 2 2 2 2 2 1 2 2 2 ...

Le jeu de données quakes est donc un data frame contenant les variables numériques lat, long et mag, les variables de type entier depth et stations et les deux variables de type facteur magfactor et region que nous lui avons ajoutées.

2.1 Parallèle avec le package ggplot2

Le package highcharter utilise la grammaire graphique tout comme le package ggplot2 qui a été présenté dans le cours. Nous créons un objet de base de classe highchart et nous lui ajoutons des couches pour modifier les paramètres du graphique. Donc de la même façon que nous créons un objet de classe ggplot auquel nous ajoutons des couches. Les deux packages possèdent une fonction de création rapide de graphiques hchart pour highcharter et qplot pour ggplot2 qui possède une structure qui est familière pour les utilisateurs de la fonction plot. Au lieu d’utiliser la fonction aes pour définir les propriétés visuelles, nous utilisons la fonction hcaes dans le package highcharter. L’opérateur d’ajout de couches est également changé, au lieu d’utiliser + nous utilisons %>%. Les fonctions appelées afin de définir les différentes couches sont également différentes entre les deux packages et certaines de ces fonctions seront présentées plus loin.

2.2 Fonction de base hchart

La fonction de création rapide d’un graphique hchart possède un seul argument object pour lequel nous définissons l’objet qui sera utilisé pour la création du graphique. Observons le code de la fonction.

hchart
## function (object, ...) 
## {
##     UseMethod("hchart")
## }
## <bytecode: 0x0000000011843f50>
## <environment: namespace:highcharter>

On voit que l’argument object est suivi de … et que cette fonction appelle une autre fonction UseMethod("hchart") afin de faire appel à la fonction la plus adaptée à la classe d’objet qui est fourni à la fonction.

L’outil graphique highcharter est adapté à plusieurs classes d’objet ce qui le rend très versatile. Joshua Kunst mentionne, sur son site web dédié au package, que highcharter accepte les data frames, la classe numeric, les données de type histogram, character, density (fonctions de densité), factors, ts (séries temporelles) et bien d’autres types de données tel qu’illustré lorsque nous regardons les différentes méthodes de la fonction hchart.

methods(hchart)
##  [1] hchart.acf*        hchart.character*  hchart.data.frame* hchart.default*   
##  [5] hchart.density*    hchart.dist*       hchart.ets*        hchart.factor*    
##  [9] hchart.forecast*   hchart.histogram*  hchart.igraph*     hchart.list*      
## [13] hchart.matrix*     hchart.mforecast*  hchart.mts*        hchart.numeric*   
## [17] hchart.prcomp*     hchart.princomp*   hchart.stl*        hchart.survfit*   
## [21] hchart.tibble*     hchart.ts*         hchart.xts*       
## see '?methods' for accessing help and source code

Les … qui suivent l’argument object sont présents afin de fournir d’autres arguments aux fonctions appelées par la fonction hchart. Afin de créer un graphique de base, deux arguments sont très pratiques bien qu’ils ne soient obligatoires. Le premier est type qui permet de spécifier le type de graphique désiré. Tout comme plot, hchart tente de choisir le meilleur type de graphique pour la classe de données fournies comme objet. Cependant, il s’avère que le type de graphique ainsi choisi n’est souvent pas bien adapté ou qu’aucun graphique n’est produit suite à une erreur due à un choix mal adapté de graphique. Le deuxième argument est l’argument mapping qui permet de fournir les données pour les axes avec la fonction hcaes qui permet de définir les « aesthetics » comme la fonction aes du package ggplot2.

2.2.1 Diagramme de dispersion avec hchart

hchart(object = quakes, type = "scatter", mapping = hcaes(x = mag, y = stations))

Le graphique obtenu est un nuage de points puisque nous avons spécifié "scatter" comme type de graphique. Les données sont le nombre de stations ayant détecté le séisme en fonction de la magnitude de séisme. La première chose intéressante à remarquer à propos du graphique obtenu est la possibilité de visualiser les données associées à chaque point. En passant sur un point il devient en surbrillance et ses données sont affichées. Cela correspond à la partie interactive des graphiques de type highchart.

Ajoutons l’argument group de la fonction hcaes afin d’identifier les points selon la région.

hchart(object = quakes, type = "scatter", mapping = hcaes(x = mag, y = stations, group = region))

Cette fois, les données sont séparées en deux catégories selon la région associée (est ou ouest). Il est possible dans la légende de cliquer sur l’un des deux groupes de données et ainsi de ne plus afficher ces données afin de visualiser un seul des groupes de données. En même temps remarquons que l’axe des données en x est automatiquement ajusté pour les données conservées lorsqu’on retire un des groupes. Ce qui est bien pratique pour des présentations de données par exemple.

2.2.2 Histogramme avec hchart

Afin de créer un histogramme avec la fonction hchart nous ferons usage de la possibilité de fournir un objet de classe histogram à la fonction.

h <- hist(quakes$mag, breaks = 30, plot = FALSE)
hchart(object = h)

L’argument breaks de la fonction hist permet de changer le pas des colonnes de l’histogramme. Une fois l’objet de type histogramme créé nous l’assignons à l’objet h qui est ensuite fourni à la fonction hchart. L’histogramme est alors créé avec les couleurs et le visuel des objets highchart et avec les fonctionnalités interactives. Le graphique est exactement le même que si nous affichons l’objet de classe histogram de base mais avec un visuel plus élaboré.

plot(h)

On remarque une autre différence en comparant les deux graphiques. Les graphiques créés avec hchart sont automatiquement ajustés à la taille de la page sur laquelle ils sont affichés et ils sont automatiquement centrés contrairement aux graphiques de base.

2.2.3 Diagramme à barres verticales ou horizontales avec hchart

Il est également possible de faire des graphiques en colonnes avec type = "column":

hchart(object = quakes$magFactor, type = "column")

ou d’avoir les barres à l’horizontal avec type = "bar"

hchart(object = quakes$magFactor, type = "bar")

2.3 Objet de classe highchart

Afin d’avoir facilement accès à toutes les options d’ajustement des graphiques de type highchart et de rendre la syntaxe du code plus facile à comprendre, il est préférable de travailler avec un opérateur de type « pipe » afin d’ajuster les éléments des graphiques un à un en faisant appel à des fonctions couche par couche. Dans le cas du package highcharter cet opérateur est le %>%. Donc, comme dans le cas du package ggplot2 nous créons un objet graphique qui s’affiche lorsqu’on le présente comme argument à la fonction print.

Avec ggplot2 nous avions:

install.packages("ggplot2", repos = "http://cran.us.r-project.org")
library(ggplot2)
diag <- ggplot(data = quakes) + geom_point(mapping = aes(x = mag, y = stations))
summary(diag)
## data: lat, long, depth, mag, stations, magFactor, region [1000x7]
## faceting: <ggproto object: Class FacetNull, Facet, gg>
##     compute_layout: function
##     draw_back: function
##     draw_front: function
##     draw_labels: function
##     draw_panels: function
##     finish_data: function
##     init_scales: function
##     map_data: function
##     params: list
##     setup_data: function
##     setup_params: function
##     shrink: TRUE
##     train_scales: function
##     vars: function
##     super:  <ggproto object: Class FacetNull, Facet, gg>
## -----------------------------------
## mapping: x = ~mag, y = ~stations 
## geom_point: na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_identity
print(diag) # ou plus simplement : diag

Que nous pouvons remplacer avec les commandes suivantes de highcharter:

diag_hc <- highchart() %>% 
  hc_add_series(data = quakes, type = "scatter", mapping = hcaes(x = mag, y = stations))
str(diag_hc)

La sortie est très longue ici alors elle n’est pas affichée.

diag_hc

Il existe différentes fonctions avec un nom comme hc_add_series_<TypeDeGraph> qui étaient utilisées auparavant, où on remplace <TypeDeGraph> par le type de graphique désiré. Cependant, lors de leur utilisation, un avertissement s’affiche qui nous dit qu’il est préférable d’utiliser simplement hc_add_series et de spécifier l’argument type si nécessaire.

2.4 Les options des objets de classe highchart

Le tableau suivant présente un résumé des fonctions qui permettent d’ajuster les différentes couches des graphiques de type highchart. La documentation de l’API des highcharts est disponible à l’adresse suivante: https://api.highcharts.com/highcharts. Il permet de connaître tous les paramètres disponibles pour chacune des fonctions. À première vu la navigation de l’API semble difficile et il n’est pas aisé de trouver les informations qu’on cherche. Cependant en s’aidant du guide PDF d’utilisation du package highcharter, qui est disponible à l’adresse suivante https://cran.r-project.org/web/packages/highcharter/highcharter.pdf, il est plus facile de naviguer dans l’API. Les fonction qui permettent d’ajuster les paramètres des graphiques, donc les différentes couches que nous ajouterons à notre objet highchart, ont toutes comme nom la forme hc_<NomDeLaCouche>. Une liste, contenant les principales fonctions nécessaires afin d’ajuster les paramètres de base des graphiques highchart, est présentée dans la suite de cette fiche. De plus, étant donné l’ampleur du package highcharter et la grande quantité de paramètres disponibles pour chacune des fonctions, ces paramètres ne seront pas tous introduits dans la présente fiche. Alors, afin de faire une recherche pour connaître d’autres paramètres ou d’autres fonction avancées du package highcharter il suffit de chercher dans la documentation PDF une fonction de la forme hc_<NomDeLaCouche> que l’on souhaite utiliser et ensuite rechercher dans le menu de gauche de la page de l’API la ligne nommée <NomDeLaCouche>. En cliquant sur cette ligne la liste de paramètres de cette couche défilera sous ce menu et en cliquant sur les différents paramètres des informations supplémentaires sur le type d’objets qu’elles acceptent sera disponible dans la fenêtre principale.

Fonction Utilité
hc_add_series Permet d’ajouter une série de données au graphique pour qu’elle y soit affichée.
hc_chart Permet d’ajuster les options pour l’aire graphique, par exemple le type de graphique, la couleur des bordures ou du fond.
hc_plotOptions Permet d’ajuster globalement les options pour toutes les séries de données, par exemple le type de points pour l’affichage des points dans un diagramme de dispersion.
hc_xAxis Permet d’ajuster l’affichage de l’axe des x, par exemple ajouter un titre d’axe ou l’épaisseur de la ligne.
hc_yAxis Permet d’ajuster l’affichage de l’axe des y, par exemple ajouter un titre d’axe ou l’épaisseur de la ligne.
hc_title Permet d’ajouter et d’ajuster les paramètre du titre du graphique.
hc_add_theme Permet de changer le design du graphique, il existe des designs faits d’avance dans le package highcharter
hc_add_annotations Permet d’ajouter des annotations au graphique
hc_colors Permet de changer les couleurs des différentes séries de données
hc_legend Permet d’ajuster les paramètres de la légende

Dans les sections suivantes, nous ajusterons graduellement les couches d’un graphique highchart en utilisant les fonctions présentées dans le tableau précédent ainsi que l’opérateur « pipe » %>%.

2.4.1 Fonction hc_add_series

Cette fonction permet d’ajouter des données qu’on souhaite afficher dans l’espace graphique. Par exemple si nous désirons créer les groupes comme nous avions fait avec l’ajout du paramètre group dans la fonction hcaes avec la fonction de base hchart. Il est encore possible de le faire ici mais afin de gérer les options pour chacun des groupes de données il est plus simple d’ajouter une série pour chaque groupe de données. Il est alors possible de faire référence aux différentes séries par le name que l’on attribut à chaque série et de modifier les options pour chaque séries individuellement dans les options plus avancées par la suite.

dispersion <- highchart() %>% 
  hc_add_series(data = quakes[which(quakes$region=='Est'),], type = "scatter", 
                mapping = hcaes(x = mag, y = stations), name = "Est") %>% 
  hc_add_series(data = quakes[which(quakes$region=='Ouest'),], type = "scatter", 
                mapping = hcaes(x = mag, y = stations), name = "Ouest")
dispersion

2.4.2 Fonction hc_chart

Avec cette fonction nous avons la possibilité d’ajuster les paramètres d’affichage de l’espace graphique. Ici nous ajoutons une bordure noire autour de l’espace graphique avec le paramètre borderColor. Le paramètre borderRadius ajoute des coins arrondis aux bordures et borderWidth modifie l’épaisseur des lignes des bordures. Finalement nous ajoutons une couleur de fond au graphique avec un dégradé avec l’option backgroundColor. L’option linearGradient détermine le sens du dégradé et stops détermine les couleurs aux deux limites du dégradé. Il faut faire attention aux couleurs utilisées pour le fond du graphique puisqu’il peut rendre les données illisibles!

dispersion <- dispersion %>%
  hc_chart(borderColor = 'black',
           borderRadius = 5,
           borderWidth = 1,
           backgroundColor = list(linearGradient = c(800, 0, 0, 0), 
                                  stops = list(list(0, 'rgb(201, 201, 201)'),
                                               list(1, 'rgb(500, 500, 500)'))))
dispersion

2.4.3 Fonction hc_xAxis et hc_yAxis

Bien que le graphique obtenu au dernier exemple aie un design plus complexe, il lui manque encore des titres d’axes afin d’identifier les données utilisées pour le construire. Les fonctions hc_xAxis et hc_yAxis sont celles qui nous permettront d’ajouter ces informations. L’option title permet de spécifier le nom des axes. Ici nous avons ajouté les symboles <b> et </b> pour chacun des axes afin que le titre apparaisse en gras. Ensuite avec les options lineWidth et lineColor nous avons épaissis les axes et les avons coloré en noir. Finalement, l’option gridLineColor dans la fonction hc_yAxis a permis de rendre les lignes horizontales pour le nombre de stations plus visibles en les colorant en noir.

dispersion <- dispersion %>%
  hc_xAxis(title = list(text = "<b>Magnitude (Richter)</b>"), lineWidth = 2, 
           lineColor = rgb(0, 0, 0)) %>%
  hc_yAxis(title = list(text = "<b>Nombre de stations</b>"), lineWidth= 2, 
           lineColor = rgb(0, 0, 0), gridLineColor = rgb(0, 0, 0))
dispersion

2.4.4 Fonction hc_title

Nous allons maintenant ajouter une autre couche afin d’ajouter un titre au graphique avec la fonction hc_title. L’argument text permet de spécifier le texte du titre.

dispersion <- dispersion %>%
  hc_title(text = "Nuage de dispersion du nombre de stations ayant détecté un séisme en fonction de la magnitude")
dispersion

2.4.5 Fonction hc_legend

La légende est également ajustable, nous pourrions la déplacer afin qu’elle soit affichée dans le coin inférieur droit du graphique et par le fait même afficher les groupes de données à la verticale.

dispersion <- dispersion %>%
  hc_legend(align = "right", verticalAlign = "bottom", layout = "vertical")
dispersion

2.4.6 Fonction hc_colors

La fonction hc_colors permet de changer la couleurs des points des données. Nous fournissons à l’argument colors un vecteur de couleurs de la même longueur que le nombre de séries de données.

dispersion <- dispersion %>%
  hc_colors(colors = c(rgb(1, 0, 0),rgb(1, 0, 1)))
dispersion

2.4.7 Fonction hc_plotOptions

Finalement, la fonction hc_plotOptions permet d’ajuster plusieurs options différentes du graphique. Entre autres, la forme des points, leur couleur (elle fait appel à hc_colors), la grosseur des points, d’ajouter des labels à des données, si une ligne relie les points elle permet d’en changer la couleur et l’épaisseur et bien d’autres paramètres visuels. Ici nous nous limitons à changer la forme de nos points pour des carrés.

dispersion <- dispersion %>%
  hc_plotOptions(series = list(marker = list(symbol = "square")))
dispersion

2.5 Autres exemples des possibilités avec highcharter

Il est possible, par exemple, de représenter des densités selon la répartition d’une variable.

highchart() %>% 
  hc_add_series(data = density(quakes$depth) , type = "area", 
                showInLegend = FALSE, color = "#F0A1EA") %>%
  hc_xAxis(title = list(text= "Profondeur du séisme"),categories=levels(quakes$stations)) %>%
  hc_yAxis(title = list(text = "densité")) %>%
  hc_title(text = "Représentation de Fonction de densité f(x) ") %>%
  hc_subtitle(text = "x: la profondeur du séisme en kilomètres")

Représenter sur le même graphe la fonction de densité de deux manières différentes.

highchart() %>% 
  # Données
  hc_add_series(data = density(quakes$stations), type = "column", name = "Histogram") %>%
  hc_add_series(data = density(quakes$stations), type = "line", name = "Densité") %>%
  # Option pour chaque series
  hc_plotOptions(
    series = list(showInLegend = TRUE, pointFormat = "{point.y}"),
    column = list(colorByPoint = TRUE, dataLabels = list(enabled = FALSE)),
    line = list(color = "black")) %>%
  # Axes
  hc_yAxis(title = list(text = "f(x)"),labels = list(format = "{value}")) %>%
  hc_xAxis(title = list(text = "Nombre de stations")) %>%
  # Titres 
  hc_title(text = " La distribution de la variable stations ") %>%
  hc_subtitle(text = "les stations qui ont detecté le seisme")
  • Représenter deux graphiques sur la même figure
highchart() %>%
  # Données
  hc_add_series(data = quakes$region, type = "column", name = "histogram") %>%
  hc_add_series(data = quakes$region, type = "pie", name = "section") %>%
  # Option graphique pour chaque series
  hc_plotOptions(
    series = list( showInLegend = TRUE),
    column = list(colorByPoint = TRUE),
    pie = list(colorByPoint = TRUE, size = 100, dataLabels = list(enabled = TRUE))) %>%
  # Axes
  hc_yAxis(
    title = list(text = "Nombre de séisme"),
    labels = list(format = "{value}")) %>% 
  hc_xAxis(title = list(text = "Région"),categories = c("Ouest", "Est")) %>%
  # Ajout de titre
  hc_title(text = "La répartition de l'emplacement du séisme" )

Et même faire des graphiques en trois dimensions.

highchart() %>% 
  hc_add_series(data = quakes$region, type = "pie", showInLegend = TRUE, depth = 25) %>%
  hc_chart(options3d = list (enabled= TRUE,alpha = 60,beta = 0)) %>%
  hc_xAxis(title = list(text= c("Ouest", "Est")),categories = levels(quakes$region)) %>%
  hc_yAxis(title = list(text = "Nombre de stations")) %>%
  hc_title(text = "Représentation du nombre de séismes par régions ")

3 Opinion et conclusion

Le package highcharter offre des graphiques avec des options visuelles de base attrayantes et une foule de possibilités d’ajustement des options d’affichage des graphiques.
Les usagers qui sont déjà à leur aise avec ggplot2 se retrouveront rapidement dans l’utilisation de highcharter puisque la syntaxe y est très similaire. L’apparence de base des graphiques de highcharter est meilleure qu’avec ggplot2 mais il est possible de s’en rapprocher avec certains ajustements supplémentaires du côté de ggplot2, notamment au niveau des couleurs.
L’avantage net de highcharter vient de l’aspect interactif des graphiques qui est présent de base dans tout les graphiques produits. Les présentations de données avec les graphiques de ce package sont donc grandement bonifiées. De plus, les graphiques sont automatiquement adaptées afin d’être ajoutés facilement à une page web sans avoir besoin d’une mise en page du format html et ils sont même utilisables avec les plateformes mobiles.
Nous pourrions penser que le package highcharter possède les caractéristiques nécessaires pour remplacer éventuellement ggplot2. Cependant, lors de son utilisation, nous avons remarqué que les graphiques produits sont plus exigeants en terme de temps et de ressources pour l’ordinateur. Donc un utilisateur ayant une machine de performance moyenne et souhaitant produire un grand nombre de graphiques risquera d’avoir des ralentissements au niveau du temps d’exécution par rapport à si les graphiques étaient produits avec ggplot2. Il est même arrivé que certains graphiques ne s’affichaient tout simplement pas et qu’ils s’affichaient seulement après quelques tentatives. Également, il faut mentionner que les graphiques highcharter sont optimisés pour les pages web. Les caractéristiques d’interaction avec les graphiques ne sont donc pas disponibles pour des documents PDF par exemple. De plus, l’utilisation du package highcharter est plus complexe que celle du package ggplot2.
La courbe d’apprentissage est plus abrupte et la documentation pour des exemples est limité pour le package R. Cependant, pour un individu avec des connaissance basiques en JavaScript, il existe d’autres exemples et des sites d’aide pour ces usagers.
On considère que les bonnes fonctionnalités de ce package sont faites principalement par JavaScript donc ça n’a pas été facile de les utiliser avec le langage R surtout qu’on a trouvé des difficultés à produire certains types de graphique.

3.1 Ouverture d’horizon

Dans cette fiche, on vous a présenté les Highcharts d’une manière générale, cependant il existe d’autres type de graphique qu’on peut produire. Si vous voulez apprendre à utiliser d’autres fonction et d’autres packages de production de graphique pour les page web, on vous recommande les Highstock qui nécessite l’installation du package quantmod et les Highmaps qui sont fournis grâce à la fonction hcmap.