Séance 1 — Lire les données avant de les dessiner
Question directrice
Qu'est-ce qu'une ligne, une variable et une mesure nous autorisent réellement à dire ?
À la fin de cette séance, vous ne regarderez plus un CSV comme une simple grille de valeurs. Vous saurez distinguer ce qui est stocké de ce qui est mesuré, repérer les ambiguïtés qui faussent une visualisation et charger un dataset réel dans un projet Vite sans lui faire dire plus qu'il ne contient.
Point de départ : vous savez lire un objet JavaScript, utiliser map et ouvrir la console du navigateur. Aucune connaissance préalable en statistique ou en visualisation n'est supposée.
Comment parcourir cette séance
Cette page peut être utilisée de trois façons :
- Avant la rencontre : parcourez les trois visualisations historiques, manipulez « Une colonne, plusieurs types » et notez une donnée de votre travail qui vous semble ambiguë.
- Pendant la rencontre : suivez le fil principal jusqu'au profilage du CSV, puis choisissez un palier de l'atelier.
- Comme référence : revenez aux sections sur les niveaux de mesure, les données manquantes et le format long lorsque vous préparez un nouveau projet.
| Temps en direct | Activité | Intention |
|---|---|---|
| 0:00–0:15 | Trois images, trois enquêtes | Comprendre ce qu'une représentation peut rendre visible — et ce qu'elle ne prouve pas |
| 0:15–0:50 | Une colonne, plusieurs types | Passer du type JavaScript au sens analytique |
| 0:50–1:20 | Mesure, forme et rôle | Déterminer les opérations et encodages plausibles |
| 1:20–1:30 | Pause | Laisser décanter les distinctions |
| 1:30–1:50 | Structure et tidy data | Transformer une table conçue pour être lue en données conçues pour être analysées |
| 1:50–2:25 | Charger, normaliser, profiler | Construire un pipeline minimal mais honnête |
| 2:25–3:00 | Atelier et débrief | Appliquer la méthode à BIXI ou à vos propres données |
1. Trois images qui ne se contentent pas d'illustrer
Une visualisation n'est pas une image ajoutée après l'analyse. Dans les meilleurs cas, elle devient une méthode d'enquête : elle rapproche des observations, rend une anomalie perceptible ou permet de défendre une décision.
Les trois œuvres suivantes sont souvent présentées comme des icônes de la visualisation. Nous allons les regarder avec admiration, mais aussi avec prudence. Une image célèbre mérite les mêmes questions qu'un dashboard contemporain : quelles données utilise-t-elle ? que code chaque marque ? quelle conclusion soutient-elle ? qu'est-ce qui manque ?
Ce que ces exemples annoncent
Ces images emploient des données très différentes : adresses et décès, positions et effectifs, mois et causes de mortalité. Elles ne pourraient pas échanger leurs encodages sans perdre leur sens.
- Une adresse prend sens comme position.
- Un effectif peut devenir une épaisseur, car il possède un zéro et des rapports significatifs.
- Un mois peut devenir un ordre cyclique, mais janvier n'est pas « plus grand » que décembre.
- Une cause de décès devient une catégorie, souvent distinguée par une teinte.
Le choix visuel commence donc bien avant la bibliothèque JavaScript. Il commence au moment où l'on décide ce que représente chaque champ.
Une précision historique utile
La formule populaire « Snow a dessiné une carte, retiré une poignée et arrêté l'épidémie » est trop simple. Snow avait déjà une hypothèse sur la transmission par l'eau, a mené des entretiens et comparé des sources d'approvisionnement. L'épidémie était déjà en déclin lorsque la poignée a été retirée. La carte demeure remarquable, mais elle faisait partie d'un faisceau d'arguments — elle n'était pas une preuve autosuffisante.
2. Le premier réflexe : demander ce qu'une colonne représente
Quand JavaScript lit un CSV, il voit surtout des chaînes de caractères. Quand PapaParse applique dynamicTyping, il peut distinguer number, boolean et null. C'est utile pour le code, mais largement insuffisant pour l'analyse.
Considérez cette ligne simplifiée d'un trajet BIXI :
{
"trip_id": "0f8a-41c2",
"start_station_id": 7036,
"start_time": "2024-07-12 08:43:11",
"duration_sec": 697,
"is_member": true,
"start_lat": 45.5214
}
start_station_id et duration_sec sont tous deux stockés comme nombres. Pourtant, faire la moyenne des durées a un sens possible ; faire la moyenne des identifiants de station n'en a aucun. Le type de stockage ne contient pas le sens métier.
Quatre lentilles, pas une seule taxonomie
Pour éviter de demander à une seule classification de tout expliquer, nous allons examiner chaque champ à travers quatre lentilles complémentaires.
| Lentille | Question | Exemple avec duration_sec |
|---|---|---|
| Stockage | Comment la valeur existe-t-elle dans le programme ? | number |
| Mesure | Quelles comparaisons et opérations ont un sens ? | ratio : 600 s est deux fois 300 s |
| Rôle analytique | À quoi sert-elle dans la question ? | mesure à résumer ou expliquer |
| Structure | Dans quel système de relations vit-elle ? | observation tabulaire, liée à un début et une fin temporels |
Cette séparation paraît formelle. En pratique, elle évite trois erreurs extrêmement communes :
- Confondre chiffre et quantité. Un code postal est composé de chiffres ou de lettres, mais reste un identifiant nominal.
- Confondre colonne et variable. Dans une table large,
trajets_janvierettrajets_fevriersont souvent deux colonnes pour une seule variable conceptuelle : le nombre de trajets, mesuré à différents mois. - Confondre donnée disponible et donnée utile. Un dataset peut contenir quarante colonnes ; votre question n'en exige peut-être que trois.
Atelier · niveau Observer
Faire l'inventaire d'une ligne
Résultat visible : Une fiche de trois champs dont le sens est plus précis que leur type JavaScript.
Choisissez une ligne d'un dataset que vous connaissez. Pour trois champs, écrivez : valeur brute, type de stockage, sens métier et opération qui serait absurde. Exemple : station_id = 7036, nombre en mémoire, identifiant de station, moyenne interdite.
3. Lentille 1 — le stockage : nécessaire, jamais suffisant
JavaScript possède peu de types primitifs : chaînes, nombres, booléens, null, undefined, bigint et symboles. Les tableaux, objets, dates et cartes sont des objets. Un CSV, lui, ne possède aucun schéma intégré : sans instruction contraire, chaque cellule arrive sous forme de texte.
Une date n'arrive pas comme une date
const raw = "2024-07-12 08:43:11";
console.log(typeof raw); // "string"
Transformer immédiatement cette chaîne avec new Date(raw) semble naturel, mais le format n'est pas un ISO 8601 complet et son fuseau n'est pas explicite. Deux navigateurs ou deux machines peuvent l'interpréter différemment.
La question professionnelle n'est donc pas seulement « puis-je parser cette date ? », mais :
- dans quel fuseau l'événement s'est-il produit ?
- la source enregistre-t-elle l'heure locale ou UTC ?
- que se passe-t-il lors du changement d'heure ?
- la précision à la seconde correspond-elle à la précision réelle du capteur ?
Un nombre peut être un identifiant
Le test le plus simple est verbal : pouvez-vous expliquer le résultat de l'opération ?
- Somme des durées : « temps cumulé des trajets » — interprétable.
- Moyenne des températures : interprétable avec précautions.
- Moyenne des identifiants de station : aucune interprétation métier.
- Somme des codes postaux : aucune interprétation métier.
Le programme vous laissera faire les quatre. Le rôle de l'analyse est précisément de refuser les deux dernières.
Type technique et type sémantique
Dans un pipeline robuste, on conserve les deux. Un schéma peut dire que station_id est une string ou un entier pour le stockage, et qu'il joue le rôle d'identifiant nominal pour l'analyse. Le premier protège le code ; le second protège le raisonnement.
4. Lentille 2 — le niveau de mesure : quelles opérations ont un sens ?
En 1946, le psychophysicien S. S. Stevens propose quatre niveaux de mesure. Cette typologie demeure utile parce qu'elle pose une question très concrète : quelles transformations préservent le sens de la variable ?
Nominal : distinguer sans ordonner
Une variable nominale découpe les observations en catégories : type d'usager, quartier, langage de programmation, station de départ. Deux valeurs peuvent être égales ou différentes ; leur ordre n'est pas intrinsèque.
On peut compter les catégories, calculer des proportions et chercher le mode. On ne calcule pas une moyenne de quartiers. Pour les représenter, on utilise surtout :
- position sur un axe catégoriel ;
- teinte distincte, avec un nombre limité de catégories ;
- forme, lorsque la couleur ne suffit pas ou ne doit pas porter seule le sens.
Ordinal : ordonner sans connaître la distance
Une échelle de satisfaction de 1 à 5 possède un ordre. Nous savons que 4 exprime davantage de satisfaction que 3 ; nous ne savons pas nécessairement si l'écart vécu entre 4 et 3 égale celui entre 2 et 1.
Le traitement pragmatique dépend du contexte. Les équipes produit calculent souvent une moyenne de scores Likert. Ce n'est pas automatiquement illégitime, mais c'est une hypothèse : on traite les écarts comme suffisamment réguliers. Une distribution des réponses ou une médiane expose davantage la structure originale.
Intervalle : comparer les écarts, pas les rapports
Pour une échelle d'intervalle, les différences ont un sens. L'écart entre 10 °C et 20 °C égale l'écart entre 20 °C et 30 °C. Le zéro est toutefois conventionnel : 20 °C n'est pas deux fois « plus chaud » que 10 °C.
Dates calendaires et températures Celsius sont les exemples classiques. On peut les placer sur un axe et calculer des différences. On évite les formulations de rapport et les encodages d'aire qui suggèrent « deux fois plus ».
Ratio : un zéro qui signifie absence de quantité
Durée, distance, masse et comptage possèdent un zéro interprétable. Un trajet de 1 200 secondes dure réellement deux fois plus longtemps qu'un trajet de 600 secondes. Les rapports et les proportions deviennent significatifs.
Ce niveau autorise davantage d'encodages quantitatifs, mais « autorisé » ne veut pas dire « lisible ». Encoder une durée par l'aire d'une bulle est mathématiquement possible et perceptuellement moins précis qu'une position ou une longueur.
Une règle de prudence
Plus une opération est ambitieuse, plus elle exige une hypothèse forte sur la mesure.
| Opération | Exigence minimale habituelle | Question à poser |
|---|---|---|
| Compter | nominal | Les catégories sont-elles mutuellement compréhensibles ? |
| Ordonner | ordinal | L'ordre est-il inhérent ou imposé par notre tri ? |
| Calculer un écart | intervalle | Les unités ont-elles une distance stable ? |
| Calculer un rapport | ratio | Le zéro signifie-t-il réellement absence de quantité ? |
Ce tableau ne dispense pas d'examiner le domaine. Il force simplement à nommer l'hypothèse avant de produire un chiffre précis.
5. Lentille 3 — la forme de la variable
Les niveaux de Stevens ne disent pas si une variable est discrète, continue, cyclique ou compositionnelle. Or cette forme influence directement le calcul et la visualisation.
Discret et continu
Une variable discrète prend des valeurs séparées : nombre de trajets, nombre de vélos disponibles, niveau de satisfaction. Une variable continue peut théoriquement prendre toute valeur dans un intervalle : durée, distance, température, latitude.
La mesure réelle est souvent quantifiée par l'instrument. Une durée enregistrée à la seconde apparaît comme un entier, mais représente un phénomène continu. Cette nuance aide à choisir entre :
- un comptage exact par barre ;
- une distribution regroupée en intervalles ;
- une courbe de densité ;
- une ligne reliant des mesures dans le temps.
Relier deux points par une ligne affirme implicitement qu'il existe une continuité ou un ordre pertinent entre eux. Une ligne entre « Montréal », « Québec » et « Gatineau » serait un trait graphique sans signification, sauf si l'ordre encode autre chose.
Cyclique
L'heure, le jour de semaine, le mois et la direction du vent se referment sur eux-mêmes : 23 h est proche de 0 h ; décembre est voisin de janvier. Un tri linéaire peut masquer cette proximité.
En pratique, on peut :
- choisir un point de coupure adapté à la question ;
- répéter une petite portion de l'axe pour rendre la continuité visible ;
- utiliser un encodage circulaire seulement si la cyclicité apporte réellement quelque chose ;
- transformer l'heure en composantes trigonométriques pour certains modèles, sans imposer ce calcul au lecteur.
Compositionnel
Des parts de marché, des budgets en pourcentage ou des répartitions de causes somment à 100 %. Si une part augmente, au moins une autre doit diminuer. Les variables ne sont pas indépendantes.
Le diagramme empilé peut montrer la composition, mais rend les catégories intermédiaires difficiles à comparer. Des small multiples ou des lignes séparées peuvent mieux révéler les évolutions. Pour l'analyse statistique avancée, les données compositionnelles demandent des transformations spécifiques ; dans ce cours, l'essentiel est de reconnaître la dépendance imposée par le total.
6. Lentille 4 — le rôle analytique et la structure
Le rôle d'une variable n'est pas fixé pour toujours. Il dépend de la question.
Identifiant, dimension, mesure
- Un identifiant distingue une observation ou permet une jointure :
trip_id,station_id. - Une dimension découpe ou organise : type d'usager, quartier, mois, station.
- Une mesure est la quantité que l'on compare, agrège ou explique : durée, nombre de trajets, température.
Dans « la durée médiane par station », station est une dimension et duration_sec une mesure. Dans « quelles stations ont changé de catégorie de fréquentation ? », la fréquentation peut devenir une dimension ordinale dérivée. Les rôles répondent à la tâche.
Grain : que représente une ligne ?
Avant tout groupBy, complétez cette phrase :
Une ligne représente…
Pour BIXI, une ligne peut représenter un trajet. Dans un fichier agrégé, elle peut représenter une station pendant une journée. Dans une table de stations, elle représente une station, indépendamment des trajets.
Mélanger ces grains produit des doubles comptes. Si vous joignez 1 000 trajets à une table où chaque station apparaît une fois, la capacité de la station sera répétée sur chaque trajet. Additionner ensuite capacity donnera une absurdité pourtant techniquement valide.
Les grandes structures rencontrées en visualisation
| Structure | Question typique | Représentations fréquentes | Transformation préalable |
|---|---|---|---|
| Table | Quelles catégories ou valeurs diffèrent ? | barres, points, distributions | filtrer, grouper, agréger |
| Série temporelle | Comment une mesure change-t-elle ? | ligne, aire, calendrier | parser les dates, choisir une granularité |
| Géospatial | Où se trouvent ou se concentrent les observations ? | points, choroplèthe, densité | projeter, joindre à une géométrie |
| Hiérarchie | Comment des éléments s'emboîtent-ils ? | arbre, treemap, sunburst | construire parent/enfant |
| Réseau | Qui est relié à qui ? | nœuds-liens, matrice | séparer nœuds et arêtes |
| Flux vivant | Que se passe-t-il maintenant ? | série glissante, statut, événement | buffer, ordre, fréquence de mise à jour |
Un CSV n'est donc pas « un type de données » au même niveau qu'un réseau. CSV décrit un format de sérialisation. Le même réseau peut être stocké dans deux CSV (nodes.csv et edges.csv), un JSON ou une base de données.
7. Tidy data — rendre la structure manipulable
Les humains apprécient souvent les tableaux larges : un mois par colonne, une station par ligne. Les outils de transformation et de visualisation travaillent plus naturellement avec des tables où chaque variable possède sa colonne.
Hadley Wickham formalise trois règles :
- chaque variable forme une colonne ;
- chaque observation forme une ligne ;
- chaque type d'unité d'observation forme une table.
Pourquoi le format long aide
Dans le format large, le mois est caché dans le nom trips_2024_01. Le schéma change lorsqu'un mois est ajouté. Dans le format long, month est une variable et trips sa mesure ; ajouter avril signifie ajouter des lignes.
Cette structure permet d'écrire une transformation qui reste valable pour tous les mois :
const byMonth = Object.groupBy(trips, trip => trip.month);
const monthlyTotals = Object.entries(byMonth).map(([month, rows]) => ({
month,
trips: rows.length,
}));
Le format long n'est pas moralement supérieur. Un rapport humain, une matrice de corrélation ou certains calculs numériques peuvent préférer une forme large. L'idée importante est de reconnaître pour quel usage la table a été façonnée.
8. Qualité des données — avant la première couleur
Une belle visualisation peut amplifier une erreur avec une efficacité remarquable. Un minimum de profilage doit précéder le design.
8.1 Valeurs manquantes : l'absence a plusieurs sens
Une cellule vide peut signifier : mesure impossible, question non applicable, refus de répondre, panne du capteur, valeur supprimée ou simple erreur d'export.
| Valeur brute | Interprétation possible | Risque |
|---|---|---|
"", espace | cellule vide | convertie en zéro par certaines opérations |
NA, N/A, NULL, - | convention humaine | plusieurs codes pour la même absence |
0 | vrai zéro ou absence mal codée | fausse baisse de moyenne |
-1, 999, 9999 | valeur sentinelle | devient un extrême dans le graphique |
| champ absent | schéma variable | undefined et branche non prévue |
Ne remplacez pas toutes les absences par zéro. Créez une politique explicite par champ : conserver, exclure, imputer, afficher comme catégorie ou signaler comme inconnue.
8.2 Unités et dénominateurs
« 120 accidents » ne permet pas de comparer deux quartiers si l'un compte dix fois plus de déplacements. Selon la question, le dénominateur pertinent peut être la population, la distance parcourue, le nombre de trajets ou le nombre d'heures d'exposition.
De même, une colonne duration sans unité est incomplète. Secondes, minutes et millisecondes peuvent produire des graphiques plausibles mais faux de facteurs 60 ou 1 000.
8.3 Couverture et biais de collecte
Un dataset ne représente jamais « le monde » ; il représente ce que le système a pu ou choisi d'enregistrer.
- Les trajets BIXI excluent les déplacements effectués autrement.
- Un sondage de développeur·ses reflète les personnes qui ont vu le questionnaire et choisi d'y répondre.
- Les requêtes 311 reflètent à la fois les problèmes urbains et la propension à les signaler.
La visualisation doit éviter de transformer une population observée en population totale sans le dire.
8.4 Provenance
Conservez avec votre projet :
- l'URL et l'organisme source ;
- la date de téléchargement ;
- la licence ;
- le dictionnaire des champs ;
- les transformations appliquées ;
- les filtres et exclusions ;
- la date ou version du code.
Ce petit journal rend le résultat reproductible et vous évite de redécouvrir six mois plus tard pourquoi le total diffère de celui du portail officiel.
Atelier · niveau Modifier
Le procès d'une moyenne
Résultat visible : Une décision documentée : calculer, remplacer par une autre statistique ou refuser l'agrégation.
Votre équipe demande « la durée moyenne d'un trajet BIXI ». Avant de calculer, listez au moins cinq vérifications : unité, valeurs manquantes, trajets anormalement longs, grain, période, population couverte, membres/occasionnels, etc. Choisissez ensuite la statistique et les filtres que vous défendriez devant un collègue.
9. Exemple travaillé — charger, normaliser et profiler un CSV
Nous allons maintenant transformer ces principes en pipeline. Le but n'est pas de fabriquer une abstraction parfaite, mais de séparer clairement quatre étapes :
- charger le texte ;
- parser la syntaxe CSV ;
- normaliser le sens des champs ;
- profiler avant de visualiser.
9.1 Pourquoi PapaParse ?
JavaScript ne possède pas de parseur CSV natif. Découper une ligne avec split(',') échoue dès qu'un champ contient une virgule entre guillemets, un retour de ligne ou un guillemet échappé.
PapaParse prend en charge cette syntaxe, les en-têtes, les lignes vides et le parsing progressif. Nous gardons toutefois le contrôle des conversions sémantiques : une inférence automatique ne peut pas deviner qu'un nombre est un identifiant.
9.2 Installer la dépendance
npm install papaparse
Si TypeScript est utilisé :
npm install --save-dev @types/papaparse
9.3 Charger sans convertir trop tôt
import Papa from "papaparse";
export async function loadCsv(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error("Impossible de charger " + url + " (HTTP " + response.status + ")");
}
const text = await response.text();
const cleanText = text.replace(/^\uFEFF/, "");
const result = Papa.parse(cleanText, {
header: true,
skipEmptyLines: "greedy",
transformHeader: header => header.trim(),
dynamicTyping: false,
});
if (result.errors.length > 0) {
console.warn("Anomalies de parsing", result.errors.slice(0, 10));
}
return result.data;
}dynamicTyping: false est volontaire. Nous allons convertir chaque champ selon son sens, plutôt que laisser le parseur transformer tout ce qui ressemble à un nombre.
9.4 Normaliser une ligne à la frontière du système
const missingTokens = new Set(["", "na", "n/a", "null", "-"]);
function cleanText(value) {
if (value == null) return null;
const text = String(value).trim();
return missingTokens.has(text.toLowerCase()) ? null : text;
}
function parseFiniteNumber(value) {
const text = cleanText(value);
if (text == null) return null;
const number = Number(text.replace(/\s/g, ""));
return Number.isFinite(number) ? number : null;
}
function parseMember(value) {
const text = cleanText(value)?.toLowerCase();
if (["1", "true", "member", "membre"].includes(text)) return true;
if (["0", "false", "casual", "occasionnel"].includes(text)) return false;
return null;
}
export function normalizeTrip(raw) {
return {
tripId: cleanText(raw.trip_id),
startStationId: cleanText(raw.start_station_id ?? raw.start_station_code),
startStationName: cleanText(raw.start_station_name ?? raw.start_station),
startTimeRaw: cleanText(raw.start_time ?? raw.start_date),
durationSec: parseFiniteNumber(raw.duration_sec),
isMember: parseMember(raw.is_member),
};
}Remarquez que startStationId reste une chaîne même si le CSV contient 7036. Nous protégeons sa fonction d'identifiant. Les opérateurs de coalescence rendent l’exemple compatible avec le schéma enrichi de la leçon (start_time, start_station_id) et l’échantillon du starter, inspiré des exports BIXI (start_date, start_station). Nous conservons startTimeRaw tant que la convention de date et de fuseau n'est pas documentée.
9.5 Profiler avant de choisir un graphique
export function profileField(rows, key) {
const values = rows.map(row => row[key]);
const present = values.filter(value => value != null);
const numeric = present.filter(value => typeof value === "number");
const counts = new Map();
for (const value of present) {
const label = String(value);
counts.set(label, (counts.get(label) ?? 0) + 1);
}
const topValues = [...counts.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([value, count]) => ({ value, count }));
return {
field: key,
rows: rows.length,
missing: values.length - present.length,
distinct: counts.size,
min: numeric.length ? Math.min(...numeric) : null,
max: numeric.length ? Math.max(...numeric) : null,
topValues,
};
}Ce profil ne remplace pas une bibliothèque de validation. Il répond aux premières questions utiles :
- combien de valeurs manquent ?
- combien de valeurs distinctes existent ?
- la plage numérique est-elle plausible ?
- une valeur domine-t-elle de manière suspecte ?
- les identifiants sont-ils réellement uniques ?
9.6 Le pipeline complet
import { loadCsv } from "./data/load-csv.js";
import { normalizeTrip } from "./data/normalize-trip.js";
import { profileField } from "./data/profile.js";
const rawRows = await loadCsv("/data/bixi-sample.csv");
const trips = rawRows.map(normalizeTrip);
console.table(trips.slice(0, 5));
console.table([
profileField(trips, "durationSec"),
profileField(trips, "startStationId"),
profileField(trips, "isMember"),
]);
À ce stade, nous n'avons produit aucun graphique. Pourtant, nous avons déjà pris des décisions de visualisation : l'identifiant ne sera pas une mesure, la durée devra être examinée comme distribution, le type d'usager deviendra une dimension et la date attend encore une convention explicite.
Le graphique vient après la table de contrôle
Dans les séances suivantes, nous conserverons toujours une petite vue tabulaire ou un profil à côté du graphique pendant le développement. Voir quelques lignes brutes reste l'un des moyens les plus rapides de repérer une agrégation trompeuse.
10. Atelier principal — construire une fiche d'identité des données
Le but n'est pas encore de produire la visualisation finale. Vous préparez un dataset assez bien compris pour que la séance 2 puisse porter sur la perception, et la séance 3 sur l'encodage avec Chart.js.
Atelier · niveau Observer
Palier 1 — Observer
Résultat visible : Une table affichant dix lignes normalisées et trois profils de colonnes.
Utilisez le bixi-sample.csv du starter. Exécutez le pipeline travaillé ci-dessus. Comparez les lignes brutes et normalisées. Repérez au moins une décision de type que PapaParse ne pouvait pas prendre seul.
Atelier · niveau Modifier
Palier 2 — Modifier
Résultat visible : Une fiche de données qui documente le grain, les types sémantiques, les valeurs manquantes et deux questions possibles.
Ajoutez au profil : pourcentage de valeurs manquantes, médiane des champs numériques et exemples de valeurs invalides. Écrivez ensuite deux questions auxquelles le dataset peut répondre et une question à laquelle il ne peut pas répondre.
Atelier · niveau Construire
Palier 3 — Construire
Résultat visible : Un petit explorateur déployé : import de fichier, profil automatique et avertissements visibles.
Ajoutez un <input type="file">, passez le fichier à PapaParse et générez automatiquement une fiche par colonne. Distinguez au minimum : valeurs présentes, cardinalité, plage numérique et exemples. Ajoutez un avertissement lorsqu'une colonne numérique possède presque autant de valeurs distinctes que de lignes : elle pourrait être un identifiant.
Questions de débrief
- Quelle colonne vous a obligé à regarder la documentation ou le contexte métier ?
- Quelle conversion automatique aurait produit une erreur silencieuse ?
- Quel choix de grain modifie le plus la question que vous pouvez poser ?
- Quelle donnée manque pour répondre à une question qui vous intéresse vraiment ?
- Quelle première visualisation testeriez-vous — et pourquoi n'est-ce encore qu'une hypothèse ?
Ce que vous devriez emporter
- Une valeur possède plusieurs types. Stockage, niveau de mesure, rôle analytique et structure répondent à des questions différentes.
- Un nombre n'est pas nécessairement une quantité. Identifiants et codes doivent être protégés des agrégations absurdes.
- Le grain est la phrase « une ligne représente… ». Tant que cette phrase est floue, les regroupements sont dangereux.
- Les opérations supposent un niveau de mesure. Compter, ordonner, soustraire et calculer un rapport n'exigent pas les mêmes propriétés.
- La forme compte. Discret, continu, cyclique et compositionnel influencent le calcul comme l'encodage.
- Tidy data facilite la transformation, pas la vérité. Une table bien formée peut encore contenir une mauvaise définition ou un biais de collecte.
- On profile avant de dessiner. Valeurs manquantes, unités, cardinalité, plage et provenance font partie du travail de visualisation.
Carte de décision réutilisable
Avant d'ouvrir Chart.js, répondez dans l'ordre :
- Question — quelle décision ou compréhension cherchons-nous ?
- Grain — que représente exactement une ligne ?
- Champs — quels sont leur sens, leur unité et leur provenance ?
- Mesure — quelles opérations sont réellement interprétables ?
- Forme — discret, continu, cyclique, compositionnel ?
- Rôle — identifiant, dimension ou mesure dans cette question ?
- Qualité — que signifient les absences, les extrêmes et la couverture ?
- Structure — faut-il filtrer, joindre, agréger ou pivoter avant de représenter ?
La séance 2 commencera là : une fois les données comprises, comment l'œil transforme-t-il des positions, longueurs, couleurs et formes en différences perçues ?
Lectures et ressources annotées
- Stevens, S. S. (1946), On the Theory of Scales of Measurement — le texte historique court qui installe nominal, ordinal, intervalle et ratio.
- Velleman, P. F. & Wilkinson, L. (1993), Nominal, Ordinal, Interval, and Ratio Typologies Are Misleading — une critique importante pour ne pas transformer Stevens en dogme.
- Wickham, H. (2014), Tidy Data — définition, exemples de données désordonnées et relation entre structure et outils.
- Munzner, T. (2009), A Nested Model for Visualization Design and Validation — pourquoi une erreur de compréhension du domaine ne se corrige pas avec un meilleur algorithme.
- BIXI Montréal, Données ouvertes — documentation et fichiers qui servent de terrain au premier cycle du cours.
- PapaParse, documentation — options de parsing, mode fichier, streaming et gestion des erreurs.