cassionAnalyse de données

Leçon 7 sur 8

Unité · Des graphiques qui ne peuvent pas dériver

Un écart d'un demi-point, remplissant la moitié du graphique

Les garçons sont présents à 88,77 % et les filles à 88,21 %. Sur un axe partant de zéro, cet écart occupe 0,6 % du graphique. Tronquez l'axe à 88-89 et il en occupe 55,7 %, un grossissement de cent fois, sans qu'aucun nombre cesse d'être juste.

PythonR135 minDéfinitions d'indicateurs de l'UNICEFCritères d'évaluation du CAD de l'OCDEEnquête SMART

Les deux mêmes nombres, quatre graphiques

Le cours de statistiques a établi que l’écart de présence entre garçons et filles vaut 0,56 point de pourcentage — significatif à p = 0,023 sur 68 267 pointages, et égal à environ un tiers de journée scolaire par enfant et par trimestre.

import matplotlib.pyplot as plt

rates = {"Boys": 0.8877, "Girls": 0.8821}
gap = (rates["Boys"] - rates["Girls"]) * 100

for lo, hi in [(0, 100), (80, 95), (87.5, 89.5), (88, 89)]:
    share = gap / (hi - lo) * 100
    print(f"axis {lo}-{hi}: the gap fills {share:.1f}% of the chart height")
# Same data, four y-limits, four different stories.
Axe L’écart occupe Grossissement
0 à 100 0,6 % du graphique ×1
80 à 95 3,7 % ×7
87,5 à 89,5 27,8 % ×50
88 à 89 55,7 % ×100

Chacun de ces graphiques est exact. Les barres sont au bon endroit, l’axe est étiqueté, les nombres sont justes. Le dernier montre une différence sur laquelle aucun programme n’agirait en train de remplir plus de la moitié de la zone de tracé.

Tronquer l’axe d’un diagramme en barres est la façon la plus efficace d’induire en erreur avec des données justes, et cela se fait bien plus souvent par accident que par dessein.

La règle, et l’exception

L’axe des valeurs d’un diagramme en barres part de zéro. Toujours. Une barre encode sa quantité par une longueur, et une longueur mesurée depuis une origine mobile n’est pas une quantité. Ce n’est pas une convention à exceptions ; c’est ce qui rend une barre lisible.

L’axe d’un graphique en ligne n’y est pas tenu. Une ligne encode l’évolution par la pente, et le lecteur compare des points entre eux plutôt qu’à l’origine. Une série de températures partant de zéro degré est une ligne plate et un graphique gâché.

fig, (a, b) = plt.subplots(1, 2, figsize=(9, 3))
a.bar(rates.keys(), rates.values())         # must include zero
a.set_ylim(0, 1)
b.plot(months, completeness)                # need not include zero
b.set_ylim(0.25, 1.0)
# geom_col() + expand_limits(y = 0). geom_line() + coord_cartesian(ylim = ...).

Et quand vous tronquez l’axe d’une ligne, dites-le sur l’axe. Une marque de rupture, ou une étiquette d’axe qui commence visiblement au-dessus de zéro, ou une note. Le lecteur qui suppose zéro et se trompe a lu le graphique à l’envers.

Quand la troncature est le choix honnête

La figure de complétude en est le cas, et il vaut la peine de préciser pourquoi.

Complétude mensuelle des rapports contre le plancher de 70 %. La complétude s’effondre à 28,9 % en août et remonte à 94,7 % en octobre, ce qui est une défaillance de notification et non un changement de l’épidémie.

values = [.921, .816, .737, .868, .842, .868, .816, .289, .447, .947, .763, .868]
print(f"range {min(values):.1%} to {max(values):.1%}")
range(values)

La complétude va de 28,9 % à 94,7 % — une étendue de 65,8 points sur un axe de 100 points. Les données emploient les deux tiers de la hauteur disponible, si bien qu’un axe partant de zéro ne gaspille presque rien et que la forme reste entièrement lisible.

La règle à appliquer est : la troncature change-t-elle l’ampleur apparente de la variation ? Ici, à peine, il n’y a donc aucun argument pour elle. Là où une troncature grossirait un écart d’un demi-point jusqu’à la moitié d’un graphique, la réponse n’est pas de tronquer plus soigneusement — c’est qu’un diagramme en barres était la mauvaise marque et que le nombre a sa place dans une phrase.

Cinq autres décisions d’axe qui changent la lecture

Les axes inversés. Un taux où plus bas vaut mieux — mortalité, abandon, retard de croissance — tracé avec la pire valeur en haut se lit comme un succès. Dites quelle direction est bonne dans l’étiquette d’axe : « Taux d’abandon (%), plus bas vaut mieux ».

Les échelles logarithmiques. Légitimes pour une courbe épidémique couvrant trois ordres de grandeur, et lues comme linéaires par presque tout public non technique. Si vous en employez une, étiquetez-la et annotez un doublement.

Les axes de pourcentage au-delà de 100. Le taux brut de scolarisation atteint 109,2 % dans les données du cours d’éducation, et un axe plafonné à 100 rogne la barre et cache le constat.

Les axes temporels à espacement irrégulier. Douze points mensuels tracés à espacement régulier alors que deux mois manquent trace une droite à travers un trou. Tracez les dates, non la séquence.

Le rapport hauteur-largeur. La même ligne à hauteur double paraît deux fois plus pentue. Il n’existe pas de choix neutre, choisissez-en donc un et employez-le pour chaque graphique du rapport, ce qui les rend au moins comparables entre eux.

fig.set_size_inches(6.5, 4)      # every figure in the report, the same shape
# ggsave(width = 6.5, height = 4) as a project default.

Le piège des données manquantes, qui est un problème d’axe

La figure de complétude existe à cause de cela et il vaut la peine de le dire directement.

Un mois sans rapports tracé comme zéro est une affirmation que rien ne s’est passé. Un mois sans rapports retiré entièrement de la série est une affirmation que le temps ne s’est pas écoulé. Ni l’une ni l’autre n’est vraie, et le graphique honnête montre le trou.

series = series.reindex(all_months)          # missing months become NaN
ax.plot(series.index, series.values)          # matplotlib breaks the line at NaN
# Do not tidyr::replace_na(0). A gap is data about the reporting system.

Les 28,9 % d’août sont une défaillance de notification, non une défaillance épidémiologique. Le cours d’épidémiologie y a consacré une leçon, et le travail du graphique est de le faire ressembler à ce que c’est — un trou dans le dénominateur — plutôt qu’à une baisse des cas.

Rapportez-le en entier

Figure axis conventions

  Bar charts use zero-based value axes without exception. Where a difference
  is too small to be visible on a zero-based axis, it is reported as a
  sentence rather than as a chart.

  Line charts may use a truncated axis where the data range justifies it; the
  axis is labelled so the truncation is visible.

  Indicators where lower is better carry "lower is better" in the axis label.

  Months with no data are drawn as gaps, never as zero. Completeness is
  reported alongside any indicator whose denominator varies by month.

  All figures in this report are drawn at 6.5 by 4 inches, so vertical
  changes are comparable between charts.

Le premier paragraphe vaut d’être adopté tel quel. « Rapportez-le comme une phrase plutôt que comme un graphique » est la décision qui aurait empêché le graphique 88-à-89, et c’est une décision d’honnêteté plutôt que de conception.

La suite

Chaque règle de ce cours est une règle que quelqu’un doit se rappeler le jour où il fait le graphique. La dernière leçon supprime le fait de s’en souvenir, en produisant la figure depuis le jeu de données — c’est ainsi que chaque graphique de cette plateforme est construit et la raison pour laquelle aucun ne peut dériver de la phrase qui l’accompagne.

Animer cette leçon

La leçon en diaporama, la prose étant reléguée dans les notes du présentateur plutôt que projetée. Produit à partir de cette page, dont il ne peut donc pas s'écarter.

Lancer le diaporamaLire les diapositives

Le PDF ne requiert aucun logiciel et se projette depuis n'importe quel poste. Le fichier PowerPoint est fait pour être modifié : appliquez la charte de votre organisation, retirez une section pour une séance plus courte, ou fusionnez deux leçons en atelier.