Cela fait maintenant quelques jours que j’essaie de reproduire un “Stream Graph” dans Tableau. Le hasard faisant bien les choses, c’est durant cette même période que Alex Jones nous offre sa version du graphique. La visualisation d’Alex utilise l’algorithme ThemeRiver en amont pour le placement des points et une préparation des données dans Alteryx. Je vous propose aujourd’hui une version alternative, entièrement réalisée dans Tableau Software.

C’est quoi un Stream Graph ?
Le “Stream Graph” est un type de graphique en aires superposées (ou “Stacked Area Graph”) construit autour d’un axe central. Il est utilisé pour visualiser des évolutions de volumes, sur plusieurs catégories. Il donne à la fois des informations visuelles sur l’évolution des parts de chaque catégorie et sur l’évolution totale du volume.

Polygones !
Polygones les amis, tout est question de polygones ! Comme beaucoup d’autres visualisations non natives de Tableau, construire un Stream Graph nécessite de les utiliser/maîtriser.

Ce tutoriel est largement inspiré de celui de l’area bump chart (en anglais) de Rody Zakovich sur son blog datatableauandme. Jetez y un œil ! 🙂
Les données
Nous allons devoir effectuer un produit cartésien (cross join) de nos données d’origine avec un second ensemble de 98 lignes. Je vous conseille donc d’agréger vos données au maximum avant de commencer à les utiliser pour éviter les problèmes de performance.
J’utilise un fichier Excel avec deux onglets.

Le premier onglet (data) contient mon agrégation sur l’axe temporel et la catégorie. Un champ technique (Link) est aussi créé afin de faciliter le produit cartésien dans Tableau.

Le second onglet (model) contient les champs techniques permettant de construire les polygones. On y retrouve la fonction sigmoid, utilisée pour créer l’aspect organique et courbe entre chaque année, aspect apprécié dans ce type de visualisation. Le champ technique “Link” est encore présent pour effectuer le produit cartésien.
Le fichier Excel complet peut être téléchargé sur ce lien.

La dernière étape consiste à joindre ces deux feuilles sur le champ “Link” dans Tableau Software.
Les calculs
Une fois vos données préparées et votre modèle chargé, le vrai travail commence. Une série de calculs plus ou moins complexes doit être réalisée avant de commencer à visualiser quelque chose.

Il y a un peu de boulot, alors au travail !
1.Partition : permet de configurer l’ensemble des points nécessaires au tracé des polygones.
IF [Position]=1
THEN [Path]
ELSE 50+(49-[Path])
END
2.YearFake : sera utilisé en temps que champ continu, dans “Colonnes”. Il s’agit de l’abscisse de nos points ( à la place du champ Year).
[Path]/49+[Year]
3.ValueCurrent : valeur courante, celle la plus à gauche de chaque courbe.
sum({FIXED [Category],[Year]: MIN([Value])})
4.ValueNext : valeur pour l’année suivante pour chaque dimension, celle la plus à droite de chaque courbe.
IFNULL(LOOKUP([3.ValueCurrent],1),0)
5.ValueX : permet de centrer la courbe par rapport à la valeur maximale possible.
MIN({MAX({FIXED [Year]: SUM([Value])/100})}
-{FIXED [Year]: SUM([Value])/100}/2)
6.Rank : rang sur la valeur courante.
RANK([3.ValueCurrent])
7.TopCurrent : position haute initiale, aussi utilisé pour obtenir l’effet cumulé des courbes (grâce au running_sum). Ce calcul est important et réutilisé dans les calculs qui suivent.
RUNNING_SUM([3.ValueCurrent])
+((SIZE()-[6.Rank])/100)+[5.ValueX]
8.TopNext : position haute suivante.
LOOKUP([7.TopCurrent],1)
9.BottomCurrent : position basse initiale.
[7.TopCurrent]-[3.ValueCurrent]
10.BottomNext : position basse suivante.
IFNULL([8.TopNext]-[4.ValueNext],0)
11.Curve : ajout de l’effet courbe pour les points intermédiaires grâce à la fonction Sigmoid. Il s’agit de l’ordonnée de nos points.
IF MIN([Position])=1 THEN
[7.TopCurrent]+(([8.TopNext]-[7.TopCurrent])*MIN([Sigmoid]))
ELSEIF MIN([Position])=2 THEN
[9.BottomCurrent]+(([10.BottomNext]-[9.BottomCurrent])*MIN([Sigmoid]))
END
12.PathPoint : donne à Tableau l’ordre des points pour les lignes à tracer.
IF [Position]=1
THEN [2.YearFake]
ELSEIF [Position]=2
THEN {MAX([Year])}+({MAX([Year])}-[2.YearFake])
ELSE [2.YearFake]+{MAX([Year])}
END
@excludeLast : permet de filtrer la dernière partie des polygones.
LOOKUP(MIN([Year]),0)<>MIN({MAX([Year])})
C’était le dernier !
La visualisation
Maintenant que le plus “fastidieux” est derrière nous, nous pouvons configurer la visualisation.
On place notre champ “Category” et “1.Partition” dans “Details” (un champ color dans couleur si nécessaire). Le type de repère utilisé doit être “Polygones”. Le champ 12.PathPoint est à placer dans “Chemin”.
On utilise le filtre @excludeLast pour enlever la dernière partie de la visualisation qui n’est pas nécessaire (toutes les valeurs après la dernière année de notre champ Year).
On place respectivement 2.YearFake et 11.Curve dans “Colonnes” et “Lignes”.
Et on paramètre les “calculs imbriqués” de notre champ calculé 11.Curve. Cette partie est la plus sensible. Elle permet de définir sur quels axes sont réalisés les calculs de table (Le RUNNING_SUM, Les LOOKUP, le RANK).
Eeeet … TADA ! Un Stream Graph sauvage devrait apparaître (Geek) ! Je vous laisse le soin de redéfinir le format du champ YearFake et de formater votre visualisation.

Une nouvelle fois, je remercie le tutoriel initial de Rody qui m’a permis de construire cette visualisation et de vous proposer cet article.
1 Comment