Communitygithub.com

Jaschenn/my-skills

Créez des graphiques statiques prêts à l'emploi avec plotnine, en chinois ou en anglais, pour des diapositives, documents, revues hebdomadaires/mensuelles et articles de journaux. Choisit le type de graphique en fonction de ce que l'utilisateur souhaite comparer (classement, tendance, variation entre deux points, composition, contribution à un changement, atteinte d'objectif, décomposition de métrique, distribution, relation, estimations avec intervalles, résumé KPI), le rend à la taille exacte de sortie (diapositive/document/colonne de journal) au format SVG, PDF et PNG, et vérifie automatiquement la mise en page. Les graphiques pour les revues d'activité suivent les conventions de reporting (▲▼ au lieu du rouge/vert, couleur uniquement pour les anomalies, légendes de base, comparaisons alignées sur la période). À utiliser lorsque l'utilisateur demande de dessiner, tracer, représenter ou visualiser des données, de créer une figure pour un deck, un rapport, une revue d'activité ou un article, ou de corriger un graphique qui semble « chargé mais qui ne dit rien ». Pas pour les graphiques interactifs (plotly/echarts) ou les tableaux de bord.

Qu'est-ce que my-skills ?

Cette compétence (skill) pour agents IA est spécialisée dans la création de graphiques statiques prêts à être insérés directement dans des présentations, documents, rapports d'activité, revues commerciales ou articles académiques, en utilisant la bibliothèque Python `plotnine`. Elle est conçue pour résoudre le problème courant des graphiques qui nécessitent de multiples ajustements manuels avant d'être présentables. La compétence guide l'agent pour choisir le type de graphique le plus approprié en fonction de la comparaison souhaitée par l'utilisateur (classement, tendance, composition, etc.), en s'appuyant sur un catalogue de fonctions dans les modules `charts.py` et `biz.py`. Elle applique automatiquement des conventions visuelles strictes (palettes de couleurs, annotations directes, tailles de sortie standards) et inclut une phase de vérification de la qualité (QA) pour détecter les problèmes de chevauchement de texte, de contraste ou de mise en page. La compétence distingue deux contextes principaux : les graphiques pour les revues d'activité (avec des conventions spécifiques comme les ▲▼ pour les variations et des couleurs limitées aux anomalies) et les graphiques pour la publication générale ou académique. Elle gère également les spécifications de sortie (taille, format SVG/PDF/PNG) pour différents supports (diapositives, documents, articles de journaux). L'agent doit suivre un workflow : identifier le contexte, sélectionner la fonction dans le tableau, spécifier la sortie, générer le graphique, analyser les résultats QA, et effectuer une vérification manuelle finale.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Jaschenn/my-skills/tree/HEAD/storytelling-viz

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

storytelling-viz : Graphiques prêts à l'emploi

L'objectif est un graphique directement utilisable dans une présentation, un document ou un journal, pas un simple histogramme bricolé. Il doit satisfaire trois points :

  • Le bon type de graphique. Le type correspond à ce qu'on compare, le focus est clair, les annotations sont directes, pas de légende.
  • Ne pas planter sur des données réelles. Les longs libellés, les valeurs négatives, les données manquantes, les catégories nombreuses et les valeurs aberrantes doivent s'afficher correctement.
  • Conforme aux spécifications de sortie. Dimensions, tailles de police, épaisseurs de ligne, format, polices intégrées sont conformes.

Cette compétence ne s'occupe que du graphique. Le choix du sujet, l'analyse et la structure du rapport ne font pas partie de son périmètre.

Workflow

  1. Déterminer le contexte. Le contexte détermine les conventions par défaut pour les couleurs, les notes de bas de page, les nombres, etc. (voir "Conventions des deux contextes") :
    • Revue d'activité : graphiques d'indicateurs opérationnels destinés aux équipes métier ou à la direction, quel que soit le rythme ou le support (revue hebdomadaire, mensuelle, tableau de bord quotidien, analyse des écarts, page de données opérationnelles pour le management / le conseil d'administration / la stratégie). Le critère est "le contenu est-il un indicateur opérationnel ? Le lecteur doit-il prendre une décision métier basée sur ce graphique ?", pas "est-ce une revue hebdomadaire ?".
    • Général / Publication : documentation d'analyse ou de recherche, résultats d'expériences, pages web, figures d'articles, etc.
    • En cas de doute, traiter comme une revue d'activité (les conventions sont plus strictes, cela ajoute seulement une ligne de note de bas de page). Le contexte "revue d'activité" nécessite d'abord la lecture de references/business.md, même si le code d'exemple semble suffisant.
  2. Choisir la fonction selon "ce qu'on compare". Voir le tableau de sélection des fonctions ci-dessous ; le même tableau pour les deux contextes.
  3. Choisir les spécifications de sortie. Utiliser spec= (diapositive, document, journal, etc.).
  4. Générer le graphique et vérifier les résultats automatiques. figure() / save() affiche QA … ok ou liste chaque avertissement après le rendu ; l'attribut .qa de la valeur de retour contient la même liste de problèmes (liste vide = succès). S'il y a des avertissements, corrigez, ne livrez pas.
  5. Ouvrir le PNG et vérifier avec la liste de contrôle. Ouvrir le PNG généré avec Read et vérifier chaque point de la liste de contrôle à la fin.

Démarrage rapide

# /// script
# dependencies = ["plotnine>=0.15,<0.16", "pandas", "pillow", "pypdf"]
# ///
import sys; sys.path.insert(0, "<skill>/scripts")
from viz_common import figure, titled, set_lang, save
import charts as C          # Fonctions graphiques générales
import biz as B             # Fonctions graphiques pour revues d'activité (peut être mélangé avec C)

set_lang("en")                                   # ou "zh" (par défaut)
c = C.bar_rank(df, "channel", "gmv", highlight="POS", top_n=8, fmt="num")
figure([[(titled(c, title="POS is the only channel that shrank"), 1)]],
       spec="doc", name="fig1", outdir="out")
save(c, "fig2", spec="journal-1col", outdir="out")   # Journal, une seule figure : pas de titre

# Revue d'activité : même figure(), mais la note de bas de page est obligatoire
k = B.kpi_cards([dict(label="GMV (MTD)", value=16.5e6, prev=15.9e6, target=57e6, progress=0.29)])
figure([[(k, 1)]], spec="doc", size=(6.5, 2), name="kpi", outdir="out",
       caption="Basis: paid-order GMV (USD); MTD to Oct 9 vs Sep 1–9.")

Tableau de sélection des fonctions

Trouvez la ligne selon ce que vous comparez. C. = charts.py, B. = biz.py ; ★ indique les fonctions conçues spécifiquement pour les revues d'activité, mais elles peuvent être utilisées dans n'importe quel contexte.

Ce qu'on compareFonctionPoints clés
Classement, composition à un instant, valeurs positives/négativesC.bar_rank(df, cat, value, highlight=, top_n=, fmt=)Tri automatique ; au-delà de top_n, fusionner en "Autres/Other" ; valeurs à l'intérieur ou à l'extérieur de la barre
Qui a apporté le changement (volume + croissance + contribution par dimension)★ B.contrib_table(df, dim, prev, cur, top_n=, growth_alert=)Barres de données pour le volume, ▲▼ pour la croissance, variation, contribution à la variation totale ; ligne total en haut
Tendance : 1 à N courbes ensembleC.line_trend(df, x, y, group=, highlight=, band=, ref=)Annotation directe en fin de courbe ; étiquettes de mois à deux niveaux automatiques pour les données mensuelles ; lignes brisées pour les données manquantes ; band= pour l'intervalle de confiance
Tendance : plusieurs groupes séparémentC.small_multiples(df, x, y, facet, highlight=)Même échelle y pour toutes les facettes ; lignes d'arrière-plan grises pour les autres groupes
Tendance : un indicateur opérationnel + comparaison avec la période précédente★ B.trend(df, date, value, compare="month"/"year", events=, as_of=, period_end=)Lignes de comparaison alignées automatiquement ; annotation des événements ; ligne pointillée + estimation pour la période en cours
Progression : cumul mensuel vs objectif★ B.cumulative_vs_target(df, date, value, target, start, end, as_of=, prior=)Cumul réel, ligne de progression de l'objectif, cumul de la période précédente, estimation basée sur la moyenne quotidienne
Réel vs objectif (plusieurs lignes)★ B.bullet(df, cat, actual, target, progress=)Barre réelle + ligne verticale objectif + ligne pointillée "ce qui devrait être fait à ce jour" ; les lignes en retard deviennent rouges
Réel vs intervalle (intervalle de prévision, plage normale)C.range_dot(df, cat, low, high, value, flag="below", bench=)Les lignes hors limites utilisent la couleur de focus ; bench= pour spécifier une ligne de référence
Deux valeurs par groupe (avant/après, prévu/réalisé)C.dumbbell(df, cat, start, end, labels=, highlight=)Point vide = début, point plein = fin ; trié par point final ; chaque ligne avec le taux de variation
Deux périodes extrêmes, tailles de groupe très différentesC.slope(df, cat, start, end, mode="change", groups=)En mode mode="change", toutes les lignes partent de 0% ; les lignes avec un point de départ à 0 sont supprimées avec un WARNING
Pont d'augmentation/diminution : période précédente → contributions → période actuelleC.waterfall(df, cat, delta, start=, end_label=)Couleurs neutres par défaut + signes + et - ; si la notion de bien/mal a un sens métier, passer up=PAL.good, down=PAL.bad
Décomposition d'indicateur (GMV = utilisateurs × fréquence × panier moyen)★ B.driver_tree(nodes)Chaque nœud affiche la valeur actuelle, la variation ▲▼, la contribution (part logarithmique pour la multiplication, variation pour l'addition)
Composition : pourcentage de chaque partie dans plusieurs groupesC.stacked_100(df, cat, part, value, order=, focus_cat=)Parties dans l'ordre naturel, dégradé monochrome ; légende dans chart.legend
Tableau à deux dimensions (groupe × temps, groupe × groupe)C.heatmap(df, x, y, value, fmt=)Blanc à monochrome, palette basée sur les quantiles 2%–98% ; texte blanc sur cellules foncées
Volume + taux (nombre de demandes et taux d'approbation)★ B.bar_line_dual(df, x, bar, line, line_range=)La seule utilisation autorisée d'un double axe : barres de volume (gauche) + ligne de taux (droite), axe du taux commençant à 0 ou sur une plage fixe
DistributionC.distribution(df, value, group=, kind="box"/"strip"/"hist")Tri par médiane ; moustaches 1,5×IQR ; échantillonnage si trop de points
Relation entre deux variables continuesC.scatter(df, x, y, label=, fit="linear", groups=, x_title=, y_title=)OLS + intervalle de confiance, affiche R² ; n'annote que les points en focus ; légende dans chart.legend avec groups=
Estimations et intervalles de confianceC.point_range(df, cat, est, low, high, ref=0)Graphique forestier ; écriture "estimation [intervalle inférieur, intervalle supérieur]" à droite
Résumé de quelques chiffres clés (haut de page de rapport)★ B.kpi_cards([dict(label, value, prev, target, progress, spark, …), …])Grands chiffres, variation ▲▼, taux d'atteinte et progression temporelle, mini-courbe de tendance ; rouge uniquement pour les anomalies

★ Les détails des paramètres (champs de kpi_cards, structure de nœuds de driver_tree, events= / as_of= de trend, prior= de cumulative_vs_target, règles d'anomalie, alignement des périodes de comparaison) se trouvent dans references/business.md.

Comment choisir quand deux options semblent adaptées :

  • B.contrib_table vs C.waterfall : Pour voir simultanément le volume, la croissance et la part, ou si plus d'environ 8 dimensions → tableau ; pour raconter "comment la période précédente s'est transformée en période actuelle" avec moins d'environ 8 éléments → waterfall. Les pages d'analyse causale mettent souvent les deux côte à côte.
  • C.line_trend vs C.small_multiples : Une ligne à mettre en avant, ou pas plus de 4 lignes → line_trend (au-delà de 4, ajouter highlight=) ; pour voir la forme de chaque groupe individuellement, avec des groupes de même importance → small_multiples. Une colonne de journal (3,5 po) ne peut pas contenir plus de 5 facettes, utiliser line_trend + highlight=.
  • Deux valeurs par groupe, d'abord regarder l'échelle des groupes : si les tailles sont proches (max / min < environ 10 fois) → C.dumbbell. Si l'échelle diffère d'un ordre de grandeur ou plus, les petits groupes deviennent illisibles sur une échelle commune, tracer directement le taux de variation : moins d'environ 8 groupes → C.slope(mode="change") ; plus de groupes → d'abord calculer la colonne de taux de variation, puis utiliser C.bar_rank(df, cat, "chg", fmt="pct"), le volume absolu étant écrit dans l'étiquette ou un tableau adjacent.

Paramètres et valeurs de retour communs à toutes les fonctions :

  • highlight= : nom de catégorie, liste ou fonction. Les éléments sélectionnés utilisent la couleur de focus, les autres deviennent gris, le nom de la catégorie est également mis en gras et coloré.
  • fmt= : "num", "pct", "pp", "int", "raw", chaîne de format ou fonction ; nd= contrôle le nombre de décimales.
  • Retourne un objet panel, à insérer directement dans figure() / save() ; chart + couche_plotnine peut être enchaîné ; chart.legend est une légende de mots colorés sur une ligne, titled() l'utilise automatiquement.

Quand aucune fonction n'est adaptée, dessiner manuellement :

  1. Utiliser C.Frame(w, h, xr, yr, left=…, …) pour réserver l'espace blanc autour en fonction de la largeur réelle du texte (text_width) ; pour l'axe, utiliser C.axis_range(lo, hi).
  2. Sur C.Canvas(), dessiner avec rect, seg, pt, text, line, band, puis générer le graphique avec cv.plot(fr).
  3. Encapsuler dans C.Chart(build), où build(w, h) calcule la disposition après avoir reçu les dimensions finales.

Ne pas coder en dur les coordonnées ou les plages d'axes dans le code.

Conventions des deux contextes

Les fonctions elles-mêmes dessinent de la même manière dans les deux contextes ; les différences concernent ces conventions par défaut. Il n'y a pas de paramètre "contexte" dans le code : les fonctions ★ intègrent automatiquement les conventions des revues d'activité (▲▼, rouge seulement pour les anomalies) et font que figure() émet un WARNING en l'absence de note de bas de page. Les graphiques C. sur la même page sont paramétrés par vous selon les conventions du tableau ci-dessous (par exemple caption=, highlight=, couleurs up= / down=).

ÉlémentGénéral / PublicationRevue d'activité
Hausse / baisseUtiliser good / bad seulement si la notion de bien/mal a un sens, et toujours accompagné d'un signe + ou – ou d'un texteToujours ▲▼ + couleur neutre, jamais de rouge/vert pour les hausses/baisses
Quand mettre du rougeSeulement pour indiquer "mauvais"Seulement pour ce qui est jugé anomalie (retard sur objectif / dépassement de seuil / au-delà de ±2σ historique) ; les anomalies positives sont seulement mises en gras
Quand dire "regardez ici" (exemple : canal qui pénalise la croissance)highlight= (couleur de focus orange)Idem ; l'orange signifie seulement "regardez ici", pas du bien ou du mal. Le caractère anormal ou non est indiqué par ▲▼ et le rouge
Note de bas de page sur les définitionsSuggéréeObligatoire (caption=) : numérateur/dénominateur, devise, fenêtre temporelle, base de comparaison ; son absence fait que figure() émet un WARNING
Base de comparaisonSelon les besoins de l'analysePar défaut : comparaison mensuelle, cumul du mois actuel vs cumul du mois précédent (même nombre de jours), atteinte d'objectif ; pour les métriques de trafic journalier, alignement sur la semaine
Période en cours non terminéeTon clair ou pointillés + "jusqu'au X"Idem, et tracer l'estimation pour la période complète basée sur la progression
NombresSelon les habitudes du domaineMontants en K/M/B ; variation de taux en pp, croissance en % ; unité écrite dans le titre ou la note
Double axeNe pas utiliserAutorisé uniquement pour "barres de volume + ligne de taux" (B.bar_line_dual)
Camembert / anneauÉviter si possibleInterdit
Spécifications courantesdoc, web, journal-*PPT utiliser slide ; documents Feishu / Lark / Notion ou chat utiliser doc (illustration PNG) ; si l'utilisateur n'a pas précisé le support, utiliser doc

Raisons et contre-exemples dans references/rules.md (la partie revue d'activité est B1–B7).

Spécifications de sortie (spec=)

specDimensions (pouces)Taille de police du corpsFormat par défautUsage
slide / slide-4x313,33×7,5 / 10×7,512 / 11,5SVG avec contours, SVG modifiable, PNG (150 dpi)Diapositives de présentation
web8×4,510,5SVG, PNG (200 dpi)Pages web, emails
doc6,5×49PDF, SVG, PNG (300 dpi)Un graphique dans un document
a4 / letterPage entière10PDF, SVG, PNGRapport pleine page
journal-1col / -1.5col / -2col3,5 / 5,35 / 7,2 de large7–7,5PDF, SVG, PNG (600 dpi)Journal (89 / 136 / 183 mm)
  • size=(w, h) peut remplacer les dimensions par défaut, par exemple pour un graphique de journal plus haut, ou une ligne de cartes KPI plus basse.
  • Les tailles de police, épaisseurs de ligne et tailles de points sont mises à l'échelle avec la spécification ; le PDF intègre les polices en Type 42, conformément aux exigences des journaux.
  • Les graphiques de journal n'ont pas de titre, la légende est dans le texte : pour un graphique unique, utiliser save(chart, name, spec="journal-1col") ; pour un graphique multi-panneaux, utiliser figure(rows, spec="journal-2col"), sans passer title=, le numéro de panneau est fourni par titled(chart, title="a").
  • figure() produit une page entière (éventuellement avec titre, sous-titre, note de bas de page, plusieurs panneaux) ; save(chart, "fig2", spec="journal-1col") exporte seulement un graphique, sans titre de page ni note de bas de page. Pour les revues d'activité, la note de bas de page étant obligatoire, utiliser figure().
  • Deux types de SVG : <nom>.svg convertit le texte en contours, identique partout ; <nom>_editable.svg conserve le texte, modifiable dans Figma / PPT, mais nécessite que la police soit installée sur l'ordinateur. Pour modifier du texte dans PPT, utiliser ce dernier, sinon utiliser le premier ou le PNG.
  • slide / web ne génèrent pas de PDF par défaut ; pour en avoir, passer formats=("pdf", "png").

Combinaison de panneaux multiples

  • figure(rows, title=, subtitle=, caption=, spec=) : rows=[[(panel, span), …], …], span est la largeur relative au sein d'une ligne.
  • La hauteur des lignes est répartie automatiquement par défaut : les lignes contenant uniquement du texte ou un tableau prennent la hauteur de leur contenu, le reste de l'espace est réparti également entre les autres lignes.
  • titled(chart, title=, legend=, note=) : ajoute un titre de panneau, une ligne de légende et une note au-dessus du graphique ; si legend= n'est pas fourni, chart.legend est utilisé automatiquement.
  • Les titres supportent le balisage enrichi : **gras** ; [phrase](focus) pour mettre en gras et colorer. Les couleurs peuvent être focus, brand, good, bad, muted, ink ou #hex.
  • Autres panneaux : text_panel(para(...)) pour un paragraphe, table_panel(rows, header=) pour un petit tableau (colonnes numériques alignées à droite automatiquement), column(a, b) pour empiler deux panneaux verticalement.
  • Chaque panneau est rendu séparément avec ses dimensions finales, donc la taille de police est en points réels ; lors de l'assemblage SVG, les identifiants des éléments de chaque panneau sont automatiquement préfixés pour éviter les conflits.

Règles visuelles (déjà exécutées par les fonctions, à suivre si vous dessinez manuellement)

  • Couleurs hiérarchisées : focus (orange) pour marquer l'unique élément à regarder, n'indique pas en soi le bien ou le mal ; brand (bleu foncé) pour les séries standard ; gris pour l'arrière-plan et les références ; l'utilisation de good / bad dépend du contexte (voir tableau ci-dessus).
  • Même couleur = même sens. Les mots-clés et les données correspondantes utilisent la même couleur ; les éléments de sens différent ne doivent pas partager une couleur.
  • Le texte doit être lisible. Le contraste du texte est d'au moins 4,5:1. Pour la couleur de focus utilisée comme texte, utiliser readable(color) pour foncer automatiquement ; pour le texte sur fond foncé, utiliser ink_on(fill). Les fonctions gèrent automatiquement, Canvas.text vérifie et avertit en cas de dessin manuel.
  • Utiliser des annotations directes au lieu de légendes. Le titre de l'axe ne doit pas être le nom du champ. Si toutes les barres sont étiquetées avec des valeurs, supprimer l'axe y et la grille.
  • Le tri doit avoir un sens. S'il y a un ordre naturel (étapes, niveaux), le suivre ; sinon, trier par valeur numérique ; placer l'élément en focus à l'endroit le plus visible ; ne pas trier alphabétiquement.
  • Axes. Les graphiques à barres doivent commencer à 0 ; les graphiques en lignes dont les données sont proches de 0 doivent commencer à 0 (zero="auto") ; les panneaux liés utilisent la même échelle ; le double axe est limité au cas "barres de volume + ligne de taux".
  • Précision. Suffisante pour distinguer. Les nombres sont toujours calculés à partir des données, formatés avec pct / pp / num / fmt_value, ne pas les écrire manuellement.
  • Choisir le graphique selon ce qu'on compare : Ne pas utiliser de barres empilées en valeur absolue pour un changement de proportion ; ne pas faire plusieurs camemberts pour des compositions de groupes ; au-delà de 4 lignes, utiliser highlight= pour souligner ou passer aux petits multiples ; si la comparaison de deux éléments dans un arbre ou un radar prend plus d'environ 2 secondes, remplacer par des barres horizontales.
  • Les problèmes de données doivent être signalés sur le graphique. Les périodes en cours non terminées utilisent des tons clairs ou des pointillés avec "jusqu'au X" ; les petits échantillons indiquent n ; pour les données manquantes, briser la ligne, ne pas relier.

Les détails et les raisons sont dans references/rules.md ; les exemples de corrections de graphiques SWD sont dans references/swd_practices.md.

Langue et typographie

  • set_lang("zh" | "en") change simultanément la police par défaut, les étiquettes de mois (chinois "1月\n2026", anglais "Jan\n2026") et "Autres/Other". Les unités monétaires sont par défaut K/M/B dans les deux langues ; pour utiliser 万/亿, utiliser set_number_style("cn"). Les étiquettes contenant du chinois utilisent automatiquement la police CJK. T("Autres", "Other") récupère la chaîne dans la langue courante.
  • Les chaînes de caractères chinoises passent automatiquement par zh() : la ponctuation devient pleine chasse, les espaces superflus autour de la ponctuation pleine chasse sont supprimés, les URL et abréviations restent inchangées.
  • Règles de césure : les nombres et les mots anglais ne sont pas coupés ; la ponctuation n'apparaît pas en début de ligne ; la parenthèse ouvrante ne reste pas en fin de ligne.
  • Les polices utilisées sont affichées au démarrage. Si un WARNING: no CJK font apparaît, installer Noto Sans SC.

Vérifications avant livraison

Vérifications automatiques (voir la sortie de figure() ou .qa) :

  • QA … ok : pas de chevauchement de texte, rien ne sort du panneau, rien n'est coupé par la zone de dessin.
  • Pas d'avertissement de contraste, ni d'avertissement rows do not fit, labels take most of the panel, cells too small, basis caption.

Vérifications manuelles (ouvrir le PNG) :

  • En cachant le titre, en regardant seulement le graphique, peut-on dire ce qu'il exprime ? N'y a-t-il qu'un seul focus ?
  • Les nombres dans le titre et les annotations proviennent-ils de la même variable que les valeurs sur le graphique ?
  • Le type de graphique correspond-il à ce qu'on compare (voir le tableau de sélection) ? Le tri a-t-il un sens ? Les échelles des panneaux liés sont-elles identiques ?
  • L'utilisation des couleurs respecte-t-elle les conventions du contexte ? Si on enlève les couleurs, le bien/mal / la hausse/baisse sont-ils encore lisibles via les symboles ou le texte ?
  • Absence de légende par défaut, de nom de champ, d'effet 3D ou de dégradé ?
  • Les dimensions et la taille de police sont-elles conformes à la spécification cible (environ 7 pt pour le corps d'un article de journal, 12 pt ou plus pour une diapositive) ? Le PDF a-t-il été exporté si nécessaire ?

Supplément pour les revues d'activité :

  • La note de bas de page sur les définitions est-elle complète ? Les chiffres sont-ils cohérents avec les autres tableaux de bord (dans le même rapport, le même nombre est-il cohérent entre les pages) ?
  • L'unité, le nombre de décimales et le format sont-ils uniformes dans tout le graphique ?

Environnement et tests

  • Dépendances : plotnine>=0.15,<0.16 (testé avec 0.15.8 + matplotlib 3.11), pandas, pillow, et pypdf pour l'export PDF. Le code est dans scripts/viz_common.py (outils de base, spécifications, export, QA), scripts/charts.py (C.) et scripts/biz.py (B.).
  • Emplacement de sortie : Définir outdir sur un répertoire visible par l'utilisateur ; ne pas écrire dans le répertoire de la compétence elle-même.
  • Galerie d'exemples : uv run references/gallery.py [outdir] (chaque fonction C., diapositive chinoise + journal anglais) ; uv run references/business_gallery.py [outdir] (chaque fonction B., diapositive chinoise + document anglais). La sortie par défaut est dans le répertoire out/ courant.
  • Tests de régression : uv run references/tests/edge_cases.py utilise 38 jeux de données limites et vérifie, dans deux spécifications (soit 76 tests), le comportement des fonctions et la conformité de la QA ; après avoir modifié une fonction de graphique, ce test doit être relancé et doit passer entièrement avant toute publication.
  • Si plotnine ne peut pas être installé dans le bac à sable : Utiliser d'abord le simulateur matplotlib dans PYTHONPATH=<skill>/scripts/plotnine_preview pour prévisualiser la mise en page et exécuter la QA (les règles d'épaisseur de ligne et de coupe sont cohérentes avec plotnine). Le QA ok du simulateur n'est pas un critère de livraison : passer le script à l'utilisateur pour qu'il l'exécute avec uv run sur sa machine, et lui indiquer clairement que ce graphique n'a pas encore été rendu et vérifié avec le vrai plotnine.

Skills associés