Autopsie d'une dataviz [10] : le diable est dans les détails

Hier, c'était premier tour de législative partielle à Strasbourg. Pour l'occasion, j'ai codé l'incontournable carte interactive pour Rue89 Strasbourg. Le truc en plus ? Plein de détails !

Priorité au mobile

Comme cela entrait directement en résonance avec des réflexions récentes, je me suis creusé la tête sur la meilleure manière d'afficher les résultats hors carte sur mobile.

Pour résumer grossièrement, quel est le rendu le plus efficace sur petit écran ? Celui-ci...

Application pour les régionales 2015

... ou celui-là ?

Application pour la législative 2016

Sans verser dans l'ergonomie de comptoir, il semble assez net que la version avec l'histogramme est la plus adaptée à la lecture mobile.

Même avec une légende où les résultats sont bien triés, on peut avoir du mal à imaginer l'avance que peut avoir le vainqueur sur les autres candidats.

Le graphe en barres permet au contraire de se représenter très rapidement ces nuances sur l'ensemble des bureaux de vote.

Et cerise sur le gâteau : l'application est en responsive, mais uniquement au chargement.

Je suis parti du principe que l'internaute débarquant sur la page de direct n'allait pas passer son temps à retailler sa fenêtre, surtout depuis un support mobile. Et adieu la complexe fonction de recadrage à la volée :-)...

Des couleurs à la fois harmonieuses et signifiantes

Les couleurs de cette carte ont ouvert un terrain de jeu qui mérite bien quelques mots.

Les cartographes se limitent en général à un maximum de neuf couleurs pour leurs cartes, ce chiffre constituant en gros un horizon indépassable.

Plus de couleurs et le lecteur se perd, moins de couleurs et on peut perdre de l'information. Evidemment, rien n'interdit de dresser une carte avec moins de neuf classes si le nombre d'unités cartographiées est limité.

Ce genre de questionnement est surtout valable pour les cartes choroplèthes, où les données représentées sont quantitatives.

Dans le cas de la législative d'hier, on était au contraire dans le domaine des cartes qualitatives : le bureau de vote se colore selon le candidat arrivé en tête, sans nuance par rapport à son score.

Ce qui peut se relever casse-tête avec un échantillon de quatorze candidats. Quatorze. Candidats. Putain.

Ceci dit, on n'est pas dans un cas d'équiprobabilité entre les différents candidats, donc :

  • pour la carte seule, cinq couleurs suffisent a priori (égalité, FN, LR, PS, EELV)
  • on n'est jamais à l'abri de certaines surprises, qu'il vaut mieux prévoir en amont
  • l'histogramme affiche l'ensemble des candidats

A ce stade, il faut arriver à composer une palette de couleurs harmonieuse ET signifiante.

Les limites des couleurs revendiquées

Une première solution consiste à utiliser la couleur revendiquée par chaque parti pour composer sa palette. J'ai pioché cette dernière sur les sites officiels ou sur les pages Facebook. Les candidats n'ayant ni l'un ni l'autre sont en gris :

Au cas où ce ne serait pas évident : les résultats cartographiés sont bidons et ne doivent pas prêter à confusion avec un score réel

Questions :

  • pouvez-vous distinguer Lutte ouvrière, le Parti communiste, le Parti Egalité et justice, et Unser Land dans l'histogramme ?
  • sur la carte, quel bleu correspond au Front national ?

Plein de partis revendiquent le rouge, couleur aux différentes significations. Signe d'alerte sur les routes, elle est plutôt associée à la gauche en Europe, mais il suffit de traverser l'Atlantique pour la rattacher au Parti républicain états-unien.

Dès lors, est-ce que ça a du sens d'associer cette couleur à un parti qui ne se revendique pas de gauche ? Et dans le cas où la couleur est brandie comme un élément de communication, est-ce bien judicieux de contribuer à le diffuser ?

J'avais donné mon avis à l'occasion d'un article sur la couleur choisie pour cartographier le Front national, et évidemment je me doute bien qu'il n'y a pas de réponse toute faite à ces questions.

Personnellement, je suis partisan d'assumer une part de subjectivité, tout simplement parce que le traitement de données implique des choix éminemment subjectifs.

Des sites spécialisés à la rescousse

Donc, pas de couleurs officielles pour notre palette, et quelques choix pour les principaux partis :

  • un rose pour le Parti socialiste
  • un bleu foncé pour Les Républicains
  • du noir pour le Front national

Concrètement, cela donne ça :

Ces teintes permettent de ne pas confondre les partis entre eux, mais elles ont un inconvénient : elle ne sont pas franchement harmonieuses. Bref, leur association pique un peu les yeux après exposition prolongée :-) !

Je me suis dit, à la lecture d'un article très exhaustif, que cela vaudrait peut-être le coup de tester une autre palette.

Je ne vais pas redérouler tout le fil de l'article plus haut (lisez-le, c'est vraiment intéressant), mais bref j'ai pioché de nouvelles couleurs sur le site LOLColors.

Ce qui nous donne :

Etonnant, non ? Les différences sont encore plus criantes en passant à une échelle supérieure :

Application pour la législative 2016

Tout ça pour dire : ne négligez pas les couleurs !

Les transitions D3 pour fermer le ban

Si vous vous êtes amusés à cliquer sur les bureaux de vote cartographiés précédemment, vous aurez remarqué des coupes sèches pour passer d'un histogramme à un autre.

L'excellente librairie Javascript D3 intègre des transitions pour fluidifier tout ça.

Il suffit, grosso modo, d'initialiser l'élément à animer à un état 0 et de paramétrer une transition pour l'amener vers son état final.

Par exemple, on peut passer pour notre histogramme de ça :

var rects = svg2.selectAll("rect")
    .data(res_bur)
            .enter()
            .append("rect")
            .attr("class","rect") // lecture des données + attribution d'une classe, jusqu'ici pas de souci
            .attr("x", function(d, i) {
                return xScale(i);
            })
            .attr("y", function(d) {
                return yScale(d.pourc);
            })
            .on('mouseover', function(d) { tip3.show(d); })
            .on('mouseout',  function(d) { tip3.hide(d); })
            .attr("width", xScale.rangeBand())
            .attr("fill", function(d,i){
                return color[i];
            })
            .attr("height", function(d) {   // et si on mettait une transition en faisant démarrer la hauteur à 0 ?
                return height2 - padding - yScale(d.pourc); 
    })

A ça :

var rects = svg2.selectAll("rect")
    .data(total_resultats)
            .enter()
            .append("rect")
            .attr("class", "rect")
            .attr("x", function(d, i) {
                return xScale(i);
            })
            .attr("y", function(d) {
                return height2 - padding;
            })
            .attr("width", xScale.rangeBand())
            .on('mouseover', function(d) { tip2.show(d); })
            .on('mouseout',  function(d) { tip2.hide(d); })
            .attr("fill", function(d,i){
                return color[i];
            })
            .attr("height", 0);  // donc on démarre à zéro

            rects.transition()  // on signifie qu'une transition démarre
            .duration(1500) // qu'elle dure 1,5 seconde
            .attr("y", function(d) {   
                return yScale(d.pourc);  // on donne l'ordonnée finale
            })
            .attr("height", function(d) {
                return height2 - padding - yScale(d.pourc);  // ainsi que la hauteur finale
            })

Ce qui nous donne :

On peut également faire appaître en fondu l'axe des ordonnées et les nom/numéro des bureaux comme ci :

svg2.append("g")
    .append("text")
            .attr("x", 30)
            .attr("y", 16)
            .attr("class","t_bureau")
            .attr("opacity", 0)
            .text(function (){
                return nom;
            })
            .transition()          
            .delay(1000)  // le délai, c'est pour faire partir la transition un peu plus tard         
            .duration(700)         
            .attr("opacity", 1.0)

svg2.append("g")
    .append("text")
            .attr("x", 30)
            .attr("y", 32)
            .attr("class","t_legende")
            .attr("opacity", 0)
            .text(function  (){
                html+="Bureau n°"+num
                    return html;
            })
            .transition()          
            .delay(1000)           
            .duration(700)         
            .attr("opacity", 1.0)

Ce qui donne pour finir (roulement de tambour) :

Par Raphaël da Silva dans la catégorie
Tags : #webdesign,