Construire une superposition de Radial Chart dans Tableau Software

Deux semaines ont passé depuis ma participation à l’IronViz. Vous êtes nombreux à me demander quelle magie se cache derrière la conception du radial chart de « weather memories ». Sans aucune magie noire ou sort, nous allons aujourd’hui construire ensemble, pas à pas, la visualisation circulaire à plusieurs couches réalisée sur scène.

 

2018-10-18_18h19_50.png
weather memories

 

La Donnée

La donnée à disposition pour l’IronViz était un ensemble de mesures météorologiques des villes des participants à la Tableau Conference, pour les 3 dernières années.

La saisonnalité annuelle des événements météorologiques n’est plus à prouver. En isolant une année, il devient donc intéressant de visualiser temps et météo sur une visualisation à caractère cyclique. La visualisation circulaire, ou « radial chart », est idéale pour ça ! Il en existe plusieurs types : radial histogram, radial bar chart, radial heatmap ou encore radial convergences.

 

giphy (2)
« Radial Chart, I choose you! »

 

Six mesures ont été sélectionnées pour la visualisation :

  • Précipitation moyenne par jour
  • Précipitation maximale par jour
  • Vitesse du vent moyenne par jour
  • Rafale de vent maximale par jour
  • Température moyenne de la nuit par jour
  • Température moyenne de la journée par jour

Le principal challenge était de pouvoir représenter tous ces indicateurs sur la représentation graphique choisie, le radial chart. Une des solutions envisageables était alors de construire plusieurs radial charts, empilés les uns sur les autres.

Les données étant confidentielles, nous travaillerons sur un faux jeu de données créé pour l’occasion.

2018-11-04_19h24_42
onglet « data »

La donnée est disponible en téléchargement sur ce lien.

Les Couches

Pour construire cette superposition de radial charts, nous avons besoin d’inclure les notions de couches (« layers »).

 

WeirdCaringAmurstarfish-size_restricted
Pas ce genre de couches, mais presque.

 

Deux solutions s’offrent à nous :

  • Dupliquer la donnée d’entrée (notre choix ici)
  • Pivoter les mesures de la donnée d’entrée (de colonnes vers lignes)

J’ai entendu parler des notions de « layers » sur le blog de datablick et l’excellent article de Chris de Martini sur les small multiple flows.

Un produit cartésien est réalisé entre les données initiales et un second ensemble de donnée. Ce second ensemble est constitué d’autant de lignes qu’il y aura de couche dans ma visualisation. Autant d’information que nécessaire peut être inclus dans ce tableau (unité, description, titre, …)

2018-11-04_19h47_19
onglet « model »
2018-11-06_11h51_41.png
le fameux produit cartésien dans Tableau sur le champ « link ».

 

Quatre couches principales vont être implémentées :

  • La couche précipitation
  • La couche vent
  • La couche température
  • La couche axes et références

 

La Visualisation

Il est conseillé de suivre ce tutoriel en téléchargeant également le tableau de bord sur Tableau Public :

https://public.tableau.com/views/greatified_com-Multi-LayeredRadialChart/multi-layeredradialchart?:embed=y&:display_count=yes&publish=yes

La base : le cercle

Le point de départ d’une visualisation circulaire est de pouvoir construire un cercle de base. Plus précisément, il s’agit de pouvoir convertir nos informations en angle, puis en coordonnées grâce aux formules usuelles de trigonométrie.

Je ne peux que vous conseiller de suivre le tutoriel de Ken Flerlage à ce sujet. Beaucoup de mes visualisations sont basées sur ses excellents articles.

C’est parti pour les calculs de base !

@angle : Pour chaque jour de l’année, nous voulons calculer l’angle correspondant.

DATEPART(‘dayofyear’,[Date])*360/365

@cos : Pour chaque jour de l’année, nous voulons calculer l’ordonnée correspondante.

cos(RADIANS([@angle]))

@sin : Pour chaque jour de l’année, nous voulons calculer l’abscisse correspondante.

sin(RADIANS([@angle]))

Pour vous assurer du résultat, je vous conseille de visualiser les coordonnées calculées en plaçant les sinus et cosinus configurés dans colonnes et lignes.

2018-11-06_09h58_49.png
Les coordonnées s’affichent pour chaque date et forment un cercle.

Tous les calculs à venir sont des variations de ces deux premières composantes.

Couche 1 : Le radial des précipitations

Le radial des précipitations est un double radial bar chart :

  • la précipitation moyenne, une barre vers l’intérieur du cercle
  • la précipitation maximale, une barre vers l’extérieur du cercle

Nous avons donc besoin de calculer les coordonnées de ces deux positions, la précipitation moyenne et la maximale. Il a également été choisi de former une barre unique reliant ces deux points, au lieu de deux barres distinctes. Ce choix est purement esthétique, et chaque barre peut être réalisée indépendamment.

Ci-dessous, les calculs de ces coordonnées. Accrochez-vous, on rentre dans le sujet !

value_prec : valeur à calculer en fonction de la position basse (position=0) ou haute (position=1) sur la barre. Si il n’y a pas de précipitation, je ne veux rien afficher. La barre est construite autour d’un cercle de rayon spécifique, [radius_prec], paramètre que nous voulons pouvoir faire varier.

IF [Precipitation Avg]>0 THEN
IF [position]=0 then [radius_prec]-[Precipitation Avg]
ELSEIF [position]=1 then [radius_prec]+[Precipitation Max] END
END

x_prec : abscisse du point.

[value_prec]*[@sin]

y_prec : ordonnée du point.

[value_prec]*[@cos]

Pour chaque date de l’année, nous avons maintenant deux points. Un point bas pour la précipitation moyenne, un point haut pour la précipitation maximale. Ces deux points doivent être reliés pour former une barre. Il suffit de placer les x et y dans colonnes et lignes et de choisir le type de repère « ligne ». Enfin, il faut paramétrer le chemin de cette ligne, une ligne par date, entre la position basse et haute. La ligne a ici l’apparence d’une barre !

2018-11-06_11h51_59

La première couche est montée ! Vous pouvez déjà filtrer sur layer=1, cela ne change pas le résultat pour l’instant mais minimise le nombre de ligne retourné.

Vous pouvez également faire varier le paramètre radius_prec pour modifier le rayon du cercle.

Couche 2 : le radial du vent

Le radial du vent est un radar/cercle, agrémenté de bulles :

  • la vitesse de vent moyenne est la position de la ligne sur le radar
  • la vitesse de la rafale maximale est la taille de la bulle sur le jour concerné

Une fois encore, nous avons donc besoin de calculer les coordonnées de ces deux mesures. Il faut également trouver un moyen d’afficher deux types de visualisation différents, le cercle et la bulle, sur un même graphique. Indice : les axes doubles sont mes amis !

Commençons par le vent :

value_wind : valeur à calculer en fonction de la vitesse du vent. Le radar/cercle est construit autour d’un cercle de rayon spécifique, [radius_wind], paramètre que nous voulons pouvoir faire varier. L’amplitude, [amplitude_wind] est également un paramètre qui doit pouvoir être modifié.

[radius_wind]+[Wind Speed Avg]/[amplitude_wind]

x_wind : abscisse du point.

[value_wind]*[@sin]

y_wind : ordonnée du point.

[value_wind]*[@cos]

Sur le même graphique, nous voulons afficher une visualisation supplémentaire pour les rafales, la bulle. Nous nous servirons des axes doubles et nous avons donc besoin de recalculer la position pour ces nouveaux axes. Ici c’est simple, la position est la même pour vent et rafale. Seul la taille de la bulle est spécifique et doit être calculée.

value_gust : taille du point, en fonction du maximum de la rafale.

max([Gust Speed Avg])

x_wind_2 : abscisse du point. Je ne veux aucun point si aucune rafale est enregistrée pour la journée.

IF [Gust Speed Avg]>0 THEN
[value_wind]*[@sin]
END

y_wind_2 : ordonnée du point.

IF [Gust Speed Avg]>0 THEN
[value_wind]*[@cos]
END

Pour chaque date de l’année, nous avons la position de la ligne pour la vitesse du vent et les positions et tailles de la bulle pour les rafales. En utilisant les coordonnées en axe double dans colonnes et lignes, je peux afficher ces deux représentations différentes. Le paramétrage du chemin de la ligne est différente de celle des précipitations. Une seule ligne est tracée autour du cercle. On utilise le champ « position » (modalité unique) par défaut dans détail, puis le chemin sur chaque modalité de la date. Le type de repère doit être modifié pour le second axe, changé en bulle.

2018-11-06_11h52_09

La seconde couche est montée. Vous pouvez également faire varier les paramètres radius et amplitude.

 

Couche 3 : le radial des températures

Le radial des températures ressemble au radial des précipitations :

  • la température moyenne de la nuit est la position basse de la barre
  • la température moyenne de la journée est la position haute de la barre

Le calcul des coordonnées est donc assez similaire à celui de la première couche.

value_temp : valeur à calculer en fonction de la position basse ou haute. Position variable autour d’un cercle de rayon [radius_temperature]. Amplitude variable grâce au paramètre [amplitude_temp].

[radius_temperature]+
IF [position]=0 then [Temperature Night Avg]
ELSEIF [position]=1 then [Temperature Day Avg] END
/[amplitude_temp]

x_temp : abscisse du point.

[value_temp]*[@sin]

y_temp : ordonnée du point.

[value_temp]*[@cos]

Le paramétrage de la visualisation est identique au paramétrage de la couche 1. Nous voulons une barre (en fait ligne), pour chaque date, entre la position basse et la position haute.

2018-11-06_11h52_26

 

 

Couche 4 : le(s) radial(s) des axes et échelles

La couche 4 sera notre couche générique d’information, de lignes de référence et d’échelle :

  • une bulle au centre pour les informations textuelles
  • une ligne à 0 pour les précipitations qui permettra de séparer visuellement les deux barres (précipitation moyenne et maximale)
  • des lignes de grilles pour chaque journée pour la vitesse du vent
  • une ligne de référence à 0 degré pour les températures
  • une ligne de référence à 30 degré pour les températures

On s’accroche, la couche 4 est en fait constituée de sous-couches !

4.gif
une couche dans la couche…

Si vous vous souvenez de l’onglet model, j’ai six positions différentes pour layer=4.

2018-11-04_19h47_19

Nous allons utiliser la superposition des couches une première fois à ce niveau de la visualisation. C’est parti !

value_init : valeur des points pour chaque position.

IF [position]=1 THEN [radius_wind]
ELSEIF [position]=2 THEN [radius_wind]+10/[amplitude_wind]
ELSEIF [position]=3 THEN [radius_temperature]+32/[amplitude_temp]
ELSEIF [position]=4 THEN [radius_temperature]+86/[amplitude_temp]
ELSEIF [position]=5 THEN [radius_prec]
END

x_init : abscisse des points.

[value_init]*[@sin]

y_init : ordonnée des points.

[value_init]*[@cos]

Plusieurs lignes sont maintenant à tracer, à des niveaux différents et avec des chemins différents. Trois sont à tracer autour du cercle, comme le vent. Une est à tracer pour chaque date, comme les précipitations et les températures. Nous devons donc avoir des champs détails et chemins spécifiques pour chaque ligne.

details_init : champ à placer dans détail pour le niveau d’agrégation à utiliser. Ici @angle est utilisé à la place de date, pour utiliser le même type de donnée que le champ position.

IF [position]=1 THEN [@angle]
ELSEIF [position]=2 THEN [@angle]
ELSEIF [position]=3 THEN [position]
ELSEIF [position]=4 THEN [position]
ELSEIF [position]=5 THEN [position]
END

path_init : champ à placer dans chemin pour le tracé de la ligne à effectuer.

IF [position]=1 THEN [position]
ELSEIF [position]=2 THEN [position]
ELSEIF [position]=3 THEN [@angle]
ELSEIF [position]=4 THEN [@angle]
ELSEIF [position]=5 THEN [@angle]
END

La bulle centrale sera créée grâce à un axe double. De nouvelles coordonnées doivent être recalculées.

x_init_2 : abscisse de la bulle centrale à 0. point unique.

IF [@angle]=360 and [position]=0 then 0.0 END

y_init_2 : ordonnée de la bulle centrale à 0. point unique.

IF [@angle]=360 and [position]=0 then 0.0 END

Pour finir, de la même manière que précédemment, nous allons placer nos champs x et y dans colonnes et lignes pour afficher les points, filtrer sur layer=0. details_init et path_init doivent être placés dans détail et chemin. L’axe double doit aussi être paramétré.

2018-11-06_11h52_40

La dernière couche est montée !

 

Superposition finale des couches

Si vous avez résisté jusqu’à la dernière couche, vous avez maintenant une idée de comment nous allons superposer tous ces layers.

x_radial : abscisse spécifique à chacun des layers.

IF [Layer]=0 THEN [x_init]
ELSEIF [Layer]=1 THEN [x_prec]
ELSEIF [Layer]=2 THEN [x_wind]
ELSEIF [Layer]=3 THEN [x_temp]
END

y_radial : ordonnée spécifique à chacun des layers.

IF [Layer]=0 THEN [y_init]
ELSEIF [Layer]=1 THEN [y_prec]
ELSEIF [Layer]=2 THEN [y_wind]
ELSEIF [Layer]=3 THEN [y_temp]
END

x_radial_2 : abscisse spécifique à chacun des layers. pour axe double.

IF [Layer]=0 THEN
[x_init_2]
ELSEIF [Layer]=2 THEN
[x_wind_2]
END

y_radial_2 : ordonnée spécifique à chacun des layers. pour axe double.

IF [Layer]=0 THEN
[y_init_2]
ELSEIF [Layer]=2 THEN
[y_wind_2]
END

Pour chaque couche, nous avions des informations différentes dans détail et chemin selon le type de visualisation à afficher : cercle ou barre.

detail : champ à placer dans détail pour le niveau d’agrégation à utiliser. Ici @angle est utilisé à la place de date, pour utiliser le même type de donnée que le champ position.

IF [Layer]=0 THEN [details_init]
ELSEIF [Layer]=1 THEN [@angle]
ELSEIF [Layer]=2 THEN [position]
ELSEIF [Layer]=3 THEN [@angle]
END

path : champ à placer dans chemin pour le tracé de la ligne à effectuer.

IF [Layer]=0 THEN [path_init]
ELSEIF [Layer]=1 THEN [position]
ELSEIF [Layer]=2 THEN [@angle]
ELSEIF [Layer]=3 THEN [position]
END

size : Des épaisseurs de lignes peuvent être configurées en fonction des layers pour le côté esthétique.

IF [Layer]=1 THEN 10
ELSEIF [Layer]=2 THEN 1
ELSEIF [Layer]=3 THEN 30
END

size_2 : taille des bulles en fonction des layers. Proportionnalité oblige.

IF [Layer]=0 THEN 2000
ELSEIF [Layer]=2 THEN [Gust Speed Avg]
END

Le paramétrage de la visualisation se fait de manière relativement simple. Vous n’avez plus besoin du champ layer dans filtre.Le champ layer peut être utilisé pour configurer les couleurs. Le champ order de l’onglet « model » peut gérer la profondeur d’affichage des différentes couches. Les valeurs des paramètres peuvent être modifié pour trouver la configuration optimale.

2018-11-06_11h52_53

 

Si vous êtes arrivé à ces mots, bravo pour votre persévérance, je savez que vous seriez assez brave (ou fou) pour suivre ce tutoriel jusqu’au bout ! Si vous avez des questions ou des difficultés à propos de cette méthode, n’hésitez pas à me joindre par les canaux traditionnels, twitter ou LinkedIn.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s