Visualisations personnalisées dans les tableaux de bord IA/BI

Important

Cette fonctionnalité est disponible en préversion publique.

Les visualisations personnalisées vous permettent de personnaliser des graphiques dans des tableaux de bord IA/BI au-delà des types de visualisation intégrés. Les visualisations personnalisées utilisent la bibliothèque Vega-Lite pour afficher des graphiques à partir d’une spécification JSON.

Les visualisations personnalisées peuvent afficher des types de graphiques spécialisés qui vont au-delà des options intégrées. L’arbre phylogénétique suivant utilise un agencement à forces dirigées pour regrouper les enregistrements liés autour des centres de groupe et de famille partagés :

Exemple de graphique phylogénétique arboriculaire

Pour construire un graphique étape par étape, voir Exemples de visualisations. Pour référencer les spécifications d’autres types de graphiques, voir Autres spécifications de graphiques.

Créer une visualisation personnalisée

Pour créer une visualisation personnalisée :

  1. Sélectionnez un jeu de données.
  2. Dans le volet de configuration de la visualisation, sélectionnez Custom Viz sous la section Visualisation avancée .
  3. Dans la section Champs , ajoutez les champs que vous souhaitez utiliser. Chaque champ a un nom unique. Référencez les champs dans votre spécification Vega-Lite en utilisant ces noms.
  4. Saisissez votre spécification JSON Vega-Lite dans l’éditeur spécification Vega-Lite.

Colonnes de jeu de données de référence

Référence aux colonnes dans une spécification Vega-Lite de l’une des manières suivantes :

  • Utilisez "field": "{columnName}". L’exemple suivant affecte la xField colonne à l’axe x :

    "encoding": {
      "x": { "field": "xField", "type": "quantitative" }
    }
    
  • Dans les expressions, utilisez datum["{columnName}"] ou datum.{columnName}. L’exemple suivant définit une nouvelle colonne x à partir des colonnes r et angle :

    { "calculate": "datum.r * cos(datum.angle)", "as": "x" }
    

Pour plus d’informations, consultez datum dans la documentation sur les expressions Vega.

Utiliser le thème du tableau de bord

Les visualisations personnalisées s’adaptent automatiquement au thème du tableau de bord, notamment en mode clair et sombre. Les éléments de graphique suivants héritent des valeurs de thème sans aucune modification de votre spécification :

  • Les polices d’axe, de légende, de titre et d’en-tête correspondent aux polices configurées du tableau de bord.
  • Les lignes de grille des axes correspondent à la couleur de la grille du tableau de bord pour le mode actif.
  • L’arrière-plan du graphique est transparent par-dessus l’arrière-plan thématique du widget.

Les paramètres que vous définissez dans le bloc de config votre spécification sont prioritaires sur les valeurs par défaut héritées.

Référencer les valeurs de thème dans les expressions

Pour appliquer un style aux marques à l’aide de valeurs adaptées au thème, faites référence aux signaux suivants dans une expression Vega-Lite ({ "expr": "..." }) :

Signal Description
colors Jetons de couleur pré-résolus du mode actif. Utilisez-les pour les valeurs courantes telles que colors.textPrimary.default, colors.gridColoret colors.markHighlightColor. N’indexez pas ceci avec [mode] ; ils sont déjà résolus.
mode Mode de couleur actif, soit 'light''dark'. Utilisez-le pour indexer les champs dashboardTheme qui proposent des variantes par mode.
dashboardTheme Thème complet configuré par le propriétaire du tableau de bord, y compris les polices (resolvedFontSettings), la palette catégorielle (visualizationColors) et les couleurs par mode (gridLineColor). Les champs avec des variantes par mode nécessitent l’index [mode] .

Les signaux colors et dashboardTheme sont indépendants. Le colors signal fournit des jetons de commodité résolus pour le mode actif, tandis que dashboardTheme expose le thème complet configuré par le propriétaire. Utilisez d’abord colors, puis utilisez dashboardTheme pour les polices, la palette complète ou toute valeur que colors ne fournit pas.

Les exemples suivants montrent comment référencer les valeurs du thème :

  • Utilisez la police du corps du tableau de bord pour une marque de texte :

    { "expr": "dashboardTheme.resolvedFontSettings.fieldValue.fontFamily" }
    
  • Utilisez la couleur de titre du tableau de bord pour le mode actif :

    { "expr": "dashboardTheme.resolvedFontSettings.fieldTitle.fontColor[mode]" }
    
  • Utilisez une couleur à partir de la palette catégorielle du tableau de bord :

    { "expr": "dashboardTheme.visualizationColors[0]" }
    

Remarque

Les colors tokens sont déjà résolus pour le mode actif. Ignorez l’index [mode] et utilisez colors.markHighlightColor, pas colors.markHighlightColor[mode]. Les champs sous dashboardTheme qui ont des variantes par mode, comme dashboardTheme.gridLineColor[mode], nécessitent l’index [mode].

Interactivité par défaut

Les visualisations personnalisées supportent le filtrage croisé, la mise en surbrillance de la sélection et le drill-through sans aucun changement dans votre spécification Vega-Lite.

  • Filtre croisé au clic : lorsqu’un utilisateur clique sur un repère, la sélection filtre les autres widgets du tableau de bord qui utilisent le même jeu de données. La sélection inclut tous les champs non agrégés dans la section Fields de la configuration des widgets. Les mesures agrégées, telles que SUM(...) ou AVG(...), sont exclues de la sélection. Si chaque champ est agrégé, cliquer sur une marque ne fait pas de filtrage croisé.
  • Mettre la sélection en surbrillance : lorsqu’un spectateur sélectionne un repère, les repères non sélectionnés s’atténuent. Les repères pleins, tels que bar, rect, arc, circle, square, geoshape, et les repères point pleins, reçoivent également un contour dans la couleur de surbrillance du thème. La ligne, la zone, la trace, le repère, la coche et les points non remplis s’atténuent seulement. Si votre spécification définit fillOpacitydéjà , opacity, stroke, ou strokeWidth sur une marque ou son encodage, votre valeur a la priorité.
  • Exploration au clic droit : Un spectateur peut faire un clic droit sur une marque et cliquer sur Explorer vers pour ouvrir une autre page filtrée par cette marque. La sélection de drill-through utilise les mêmes champs que la sélection cross-filter. Pour configurer les pages cibles, voir Utiliser le drill-through pour filtrer les données.

Le tableau de bord ajoute la sélection par défaut du filtre croisé uniquement aux spécifications avec une seule vue : un niveau mark supérieur et sans layer, concat, hconcat, vconcat, facet, , ou repeat. Pour d’autres spécifications, déclarez vous-même le paramètre de sélection. Voir Filtrer les autres widgets lors de la sélection. Lorsque vous déclarez le paramètre, le tableau de bord met en évidence la sélection dans chaque vue de la spécification. Le drill-through fonctionne également avec des spécifications en couches et multi-vues.

L’interactivité par défaut n’ajoute pas d’infobulles. Pour afficher une infobulle, posez "tooltip": true sur le repère ou ajoutez un encodage tooltip.

Désactiver le filtre croisé par défaut

Si votre spécification définit ses propres interactions de clics, désactivez le filtre croisé par défaut afin que le tableau de bord affiche la spécification telle qu’elle est écrite :

  1. Ouvrez la visualisation personnalisée dans le panneau de configuration de la visualisation.
  2. Désactiver le filtre croisé par défaut.

Lorsque le paramètre est désactivé, le tableau de bord n’ajoute pas de paramètre de sélection ni ne surligne les codages dans votre spécification. Le comportement suivant reste le même :

  • Un paramètre que vous déclarez databricks_mark_selection filtre toujours le tableau de bord.
  • Le drill-through au clic droit fonctionne toujours.

Filtrer les autres widgets en fonction de la sélection

Pour contrôler quels champs un clic sélectionne, ou pour effectuer un filtrage croisé à partir d’une spécification en couches ou multi-vues, déclarez un paramètre de sélection de points avec le nom réservé databricks_mark_selection. Le renderer détecte ce nom et connecte la sélection à l’état de filtrage croisé du tableau de bord. Lorsque votre spécification déclare ce paramètre, le tableau de bord l’utilise à la place de la sélection par défaut du filtre croisé. Le drill-through utilise également les champs figurant dans la liste des paramètres.

"params": [
  {
    "name": "databricks_mark_selection",
    "select": { "type": "point", "fields": ["categoryName"] }
  }
]

Les conditions suivantes s'appliquent :

  • Le paramètre name doit être exactement databricks_mark_selection. Tout autre nom est traité comme un paramètre normal et ne pilote pas le filtrage croisé.
  • select.type doit être point. Les sélections par intervalle (au pinceau) ne sont pas prises en charge comme sources de filtres croisés. Un paramètre avec select.type: "interval" affiche l’avertissement Interval cross-filter not supported et n’effectue pas de cross-filter.
  • select.fields doit répertorier les noms de champs définis dans la section Champs de la configuration du widget, et non les noms de colonnes brutes.
  • Lister uniquement les champs de dimension (regroupement) dans select.fields. Les mesures agrégées, telles que SUM(...) ou AVG(...), ne peuvent pas conduire un filtre croisé.
  • Pour sélectionner plusieurs champs, indiquez-les ensemble : "fields": ["categoryName", "regionName"].

Mettre en surbrillance les marques sélectionnées

Le tableau de bord met en évidence les repères sélectionnés par défaut. Voir Interactivité par défaut. Pour personnaliser la surbrillance, utilisez les conditions stroke et strokeWidth sur une marque basée sur le remplissage (comme bar, arc ou rect) et gardez l’encodage color lié à votre champ. Utilisez { "expr": "colors.markHighlightColor" } pour le trait afin que la surbrillance reste lisible dans les modes clair et sombre.

L’exemple suivant filtre le reste du tableau de bord par categoryName lorsqu’on clique sur une barre. Les barres sélectionnées reçoivent un contour assorti au thème, tandis que les barres non sélectionnées s’atténuent tout en conservant leur codage couleur.

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
  "data": { "name": "databricks_query" },
  "width": "container",
  "height": "container",
  "config": { "autosize": { "type": "fit", "contains": "padding" } },
  "params": [
    {
      "name": "databricks_mark_selection",
      "select": { "type": "point", "fields": ["categoryName"] }
    }
  ],
  "mark": { "type": "bar", "stroke": null },
  "encoding": {
    "x": { "field": "categoryName", "type": "nominal" },
    "y": { "field": "salesValue", "type": "quantitative" },
    "color": { "field": "categoryName", "type": "nominal" },
    "fillOpacity": {
      "condition": { "param": "databricks_mark_selection", "value": 1 },
      "value": 0.3
    },
    "stroke": {
      "condition": {
        "param": "databricks_mark_selection",
        "empty": false,
        "value": { "expr": "colors.markHighlightColor" }
      },
      "value": null
    },
    "strokeWidth": {
      "condition": { "param": "databricks_mark_selection", "empty": false, "value": 2 },
      "value": 0
    }
  }
}

Redimensionnez automatiquement un graphique

Pour que le redimensionnement d’un graphique corresponde à son conteneur, ajoutez les paramètres suivants au niveau supérieur de votre spécification :

"width": "container",
"height": "container",
"config": {
  "autosize": {
    "type": "fit",
    "contains": "padding"
  }
}

Exemples de visualisations

Les exemples suivants expliquent étape par étape la création d’une visualisation personnalisée, d’un simple graphique en couches à un arbre phylogénétique plus avancé.

Graphique en couches avec une moyenne mobile

Cet exemple crée un graphique multicouche qui représente des points de données bruts de température avec une ligne de moyenne mobile en superposition, à l’aide de données météorologiques provenant des jeux de données d’exemple Databricks.

Graphique de température en couches avec une courbe de moyenne glissante rouge sur les points diffusés

  1. Créez un jeu de données avec la requête suivante :

    SELECT date, temperature AS temp_max
    FROM samples.accuweather.historical_hourly_imperial
    WHERE city_name = 'singapore'
    ORDER BY date;
    
  2. Dans le volet de configuration de visualisation, sous Avancé, sélectionnez Custom Viz.

  3. Sélectionnez le jeu de données que vous avez créé à l’étape précédente.

  4. Dans la section Champs, ajoutez un champ pour la colonne Date et définissez son Name sur date.

  5. Ajoutez un champ pour la colonne de température et définissez son Name sur temp_max.

  6. Copiez la spécification suivante dans l’éditeur de spécifications Vega-Lite. Si l’axe des x est tronqué, voir Redimensionner un graphique automatiquement.

    Spécification JSON
    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "width": "container",
      "height": "container",
      "config": {
        "autosize": { "type": "fit", "contains": "padding" }
      },
      "data": { "name": "databricks_query" },
      "transform": [
        {
          "window": [{ "field": "temp_max", "op": "mean", "as": "rolling_mean" }],
          "frame": [-15, 15]
        }
      ],
      "encoding": {
        "x": { "field": "date", "type": "temporal", "title": "Date" },
        "y": {
          "type": "quantitative",
          "scale": { "zero": false },
          "axis": { "title": "Max temperature and rolling mean" }
        }
      },
      "layer": [
        {
          "mark": { "type": "point", "opacity": 0.3 },
          "encoding": { "y": { "field": "temp_max", "title": "Max temperature" } }
        },
        {
          "mark": { "type": "line", "color": "red", "size": 3 },
          "encoding": { "y": { "field": "rolling_mean", "title": "Rolling mean of max temperature" } }
        }
      ]
    }
    

Arbre phylogénétique

Cet exemple utilise un petit ensemble de données d’échantillons pour construire l’arbre phylogénétique montré en haut de cette page. Vega-Lite trace les points aux coordonnées que vous fournissez, mais ne calcule pas la position des nœuds pour un diagramme réseau lui-même. Ce calcul se fait dans la requête avant que les données n’atteignent le graphique, où la requête précalcule les coordonnées x et y de chaque point. La requête émet trois types d’enregistrements que la spécification rend en couches séparées : path les enregistrements dessinent les branches courbes, node les enregistrements dessinent les cercles de feuilles, et label les enregistrements positionnent les libellés de groupe.

  1. Téléchargez les données d’exemple. Chaque ligne représente une découverte fossile, avec dig_longitude et dig_latitude indiquant ses coordonnées de site de fouille.

    Téléchargez les données d’exemple

  2. Dans la barre latérale, cliquez sur Icône Tableaux de bordTableaux de bord.

  3. Cliquez sur Créer un tableau de bord.

  4. Cliquez sur l'onglet Données .

  5. Cliquez sur Ajouter des données, puis cliquez sur Importer des données.

  6. Insérez le fichier téléchargé dans le volet Créer ou modifier une table à partir du téléversement de fichier.

  7. Choisissez le catalogue et le schéma où vous souhaitez stocker la table, puis entrez un nom de table.

  8. Cliquez sur Créer une table. Le tableau complet est automatiquement ajouté sous forme de jeu de données.

  9. Cliquez sur Ajouter un jeu de données SQL et collez la requête. Dans la clause de requête FROM, remplacez les noms du catalogue, du schéma et de la table par ceux que vous avez utilisés lors de la création de la table.

  10. Créez la visualisation personnalisée en suivant les étapes de Créer une visualisation personnalisée. Dans la section Champs, ajoutez les champs suivants, en utilisant chaque nom de champ comme son Nom : record_type, x, y, fossil_tag, point_order, suborder, roar_score, clade_label, genus_symbol, family_taxon et label_text. Utilisez la spécification comme Vega-Lite JSON.

Requête SQL
WITH base AS (
  SELECT
    fossil_tag,
    genus_symbol,
    clade_label,
    suborder,
    family_taxon,
    dig_longitude,
    dig_latitude,
    roar_score
  FROM
    `my_catalog`.`default`.`dino_table`
),
root_pt AS (
  SELECT
    AVG(dig_longitude) AS rx,
    AVG(dig_latitude) AS ry
  FROM
    base
),
group_pts AS (
  SELECT
    suborder,
    AVG(dig_longitude) AS gx,
    AVG(dig_latitude) AS gy
  FROM
    base
  GROUP BY
    suborder
),
family_pts AS (
  SELECT
    suborder,
    family_taxon,
    AVG(dig_longitude) AS fx,
    AVG(dig_latitude) AS fy
  FROM
    base
  GROUP BY
    suborder,
    family_taxon
),
ctx AS (
  SELECT
    b.fossil_tag,
    b.suborder,
    b.family_taxon,
    b.clade_label,
    b.genus_symbol,
    b.dig_longitude,
    b.dig_latitude,
    b.roar_score,
    r.rx,
    r.ry,
    g.gx,
    g.gy,
    f.fx,
    f.fy
  FROM
    base b
      CROSS JOIN root_pt r
      JOIN group_pts g
        ON b.suborder = g.suborder
      JOIN family_pts f
        ON b.suborder = f.suborder
        AND b.family_taxon = f.family_taxon
),
waypoints AS (
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    0 AS point_order,
    rx AS x,
    ry AS y
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    1,
    rx + 0.30 * (gx - rx),
    ry + 0.30 * (gy - ry)
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    2,
    gx + 0.15 * (fx - gx),
    gy + 0.15 * (fy - gy)
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    3,
    gx + 0.50 * (fx - gx) + 0.03 * (dig_longitude - fx),
    gy + 0.50 * (fy - gy) + 0.03 * (dig_latitude - fy)
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    4,
    fx + 0.15 * (dig_longitude - fx),
    fy + 0.15 * (dig_latitude - fy)
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    5,
    fx + 0.65 * (dig_longitude - fx),
    fy + 0.65 * (dig_latitude - fy)
  FROM
    ctx
  UNION ALL
  SELECT
    fossil_tag,
    suborder,
    family_taxon,
    clade_label,
    genus_symbol,
    roar_score,
    6,
    dig_longitude,
    dig_latitude
  FROM
    ctx
)
SELECT
  fossil_tag,
  suborder,
  point_order,
  x,
  y,
  family_taxon,
  clade_label,
  genus_symbol,
  roar_score,
  'path' AS record_type,
  CAST(NULL AS STRING) AS label_text
FROM
  waypoints
UNION ALL
SELECT
  fossil_tag,
  suborder,
  99 AS point_order,
  dig_longitude AS x,
  dig_latitude AS y,
  family_taxon,
  clade_label,
  genus_symbol,
  roar_score,
  'node' AS record_type,
  CAST(NULL AS STRING) AS label_text
FROM
  base
UNION ALL
SELECT
  g.suborder AS fossil_tag,
  g.suborder AS suborder,
  100 AS point_order,
  g.gx
    + (g.gx - r.rx)
      * CASE LOWER(g.suborder)
        WHEN 'titanosauria' THEN 0.10
        WHEN 'hadrosauria' THEN 0.25
        WHEN 'ornithopoda' THEN 1.30
        WHEN 'stegosauria' THEN 0.73
        ELSE 0.55
      END AS x,
  g.gy
    + (g.gy - r.ry)
      * CASE LOWER(g.suborder)
        WHEN 'titanosauria' THEN 0.10
        WHEN 'hadrosauria' THEN 0.25
        WHEN 'ornithopoda' THEN 1.30
        WHEN 'stegosauria' THEN 0.73
        ELSE 0.55
      END AS y,
  CAST(NULL AS STRING) AS family_taxon,
  CAST(NULL AS STRING) AS clade_label,
  CAST(NULL AS STRING) AS genus_symbol,
  CAST(NULL AS DOUBLE) AS roar_score,
  'label' AS record_type,
  g.suborder AS label_text
FROM
  group_pts g CROSS JOIN root_pt r

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": { "name": "databricks_query" },
  "width": "container",
  "height": "container",
  "background": "white",
  "config": {
    "autosize": { "type": "fit", "contains": "padding" },
    "view": { "stroke": null }
  },
  "layer": [
    {
      "transform": [{ "filter": "datum.record_type === 'path'" }],
      "mark": {
        "type": "line",
        "interpolate": "basis",
        "strokeCap": "round",
        "strokeJoin": "round"
      },
      "encoding": {
        "x": {
          "field": "x",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "y": {
          "field": "y",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "detail": { "field": "fossil_tag", "type": "nominal" },
        "order": { "field": "point_order", "type": "quantitative" },
        "color": {
          "field": "suborder",
          "type": "nominal",
          "scale": { "scheme": "tableau10" },
          "legend": null
        },
        "opacity": { "value": 0.3 },
        "strokeWidth": { "value": 0.8 }
      }
    },
    {
      "transform": [{ "filter": "datum.record_type === 'node'" }],
      "mark": {
        "type": "circle",
        "opacity": 0.9,
        "stroke": "white",
        "strokeWidth": 0.3
      },
      "encoding": {
        "x": {
          "field": "x",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "y": {
          "field": "y",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "color": {
          "field": "suborder",
          "type": "nominal",
          "scale": { "scheme": "tableau10" },
          "legend": { "title": "Suborder", "orient": "right" }
        },
        "size": {
          "field": "roar_score",
          "type": "quantitative",
          "scale": { "domain": [0, 100], "range": [4, 150] },
          "legend": null
        },
        "tooltip": [
          { "field": "clade_label", "title": "Clade" },
          { "field": "genus_symbol", "title": "Symbol" },
          { "field": "suborder", "title": "Suborder" },
          { "field": "family_taxon", "title": "Family" },
          { "field": "roar_score", "title": "Roar Score", "format": ".1f" }
        ]
      }
    },
    {
      "transform": [{ "filter": "datum.record_type === 'label'" }],
      "mark": {
        "type": "text",
        "fontSize": 12,
        "fontWeight": "bold",
        "opacity": 0.85
      },
      "encoding": {
        "x": {
          "field": "x",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "y": {
          "field": "y",
          "type": "quantitative",
          "axis": null,
          "scale": { "zero": false, "nice": false }
        },
        "text": { "field": "label_text", "type": "nominal" },
        "color": {
          "field": "suborder",
          "type": "nominal",
          "scale": { "scheme": "tableau10" },
          "legend": null
        }
      }
    }
  ]
}

Plus de spécifications des graphiques

Les spécifications suivantes montrent les graphiques qui ne sont pas disponibles en tant que types de visualisation intégrés. Pour plus d’exemples, consultez les galeries d’exemples Vega-Lite.

Graphique à puces

Exemple de graphique à puces.

Définissez categoryField, currentField, paceFieldet targetField dans la section Champs .

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "width": "container",
  "height": "container",
  "data": { "name": "databricks_query" },
  "config": {
    "autosize": { "type": "fit", "contains": "padding" }
  },
  "transform": [
    {
      "fold": ["targetField", "paceField", "currentField"],
      "as": ["measure_name", "measure_value"]
    },
    {
      "calculate": "toNumber(datum.measure_value)",
      "as": "measure_value"
    },
    {
      "calculate": "{ \"targetField\": \"Target\", \"paceField\": \"Pace\", \"currentField\": \"Current\" }[datum.measure_name]",
      "as": "measure_label"
    },
    {
      "calculate": "indexof([\"Target\", \"Pace\", \"Current\"], datum.measure_label)",
      "as": "measure_order"
    }
  ],
  "layer": [
    {
      "mark": "bar",
      "params": [
        {
          "name": "legend_click",
          "select": { "type": "point", "fields": ["measure_label"] },
          "bind": "legend"
        }
      ],
      "encoding": {
        "color": { "field": "measure_label" },
        "opacity": { "value": 0 }
      }
    },
    {
      "transform": [{ "filter": { "param": "legend_click" } }],
      "layer": [
        {
          "layer": [
            {
              "mark": { "type": "bar", "tooltip": true },
              "encoding": { "color": { "field": "measure_label", "legend": null } },
              "transform": [{ "filter": { "field": "measure_label", "oneOf": ["Pace"] } }]
            },
            {
              "mark": { "type": "bar", "height": 7, "tooltip": true },
              "encoding": { "color": { "field": "measure_label", "legend": null } },
              "transform": [{ "filter": { "field": "measure_label", "oneOf": ["Current"] } }]
            },
            {
              "mark": { "type": "tick", "tooltip": true, "thickness": 3 },
              "encoding": { "color": { "field": "measure_label", "legend": null } },
              "transform": [{ "filter": { "field": "measure_label", "oneOf": ["Target"] } }]
            }
          ],
          "encoding": {
            "x": {
              "field": "measure_value",
              "type": "quantitative",
              "stack": null,
              "title": "Value",
              "axis": { "orient": "bottom" }
            },
            "color": {
              "scale": {
                "domain": ["Target", "Pace", "Current"],
                "range": ["#000000", "#bcbcbc", "#A66BBF"]
              }
            },
            "order": {
              "field": "measure_order",
              "type": "quantitative",
              "sort": "descending"
            }
          }
        }
      ],
      "encoding": {
        "y": {
          "field": "categoryField",
          "type": "ordinal",
          "title": "Category",
          "axis": { "labelOverlap": true }
        },
        "tooltip": [
          { "field": "categoryField", "type": "nominal", "title": "Category" },
          { "field": "currentField", "type": "quantitative", "title": "Current" },
          { "field": "paceField", "type": "quantitative", "title": "Pace" },
          { "field": "targetField", "type": "quantitative", "title": "Target" }
        ]
      }
    }
  ]
}

Jauge

Exemple de graphique de jauge.

Définissez $valueField et $totalField dans la section Champs .

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
  "width": "container",
  "height": "container",
  "data": { "name": "databricks_query" },
  "config": {
    "concat": { "spacing": 0 },
    "autosize": { "type": "fit", "contains": "padding" }
  },
  "params": [
    { "name": "ring_max", "expr": "min(width, height) / 2 - 16" },
    { "name": "ring_width", "expr": "max(12, (min(width, height) / 2) * 0.12)" },
    { "name": "ring_gap", "expr": "max(4, (min(width, height) / 2) * 0.03)" },
    { "name": "label_color", "value": "#000000" },
    { "name": "ring_background_opacity", "value": 0.3 },
    { "name": "ring0_percent", "value": 100 },
    { "name": "ring0_outer", "expr": "ring_max + 2" },
    { "name": "ring0_inner", "expr": "ring_max + 1" },
    { "name": "ring1_outer", "expr": "ring0_inner - ring_gap" },
    { "name": "ring1_inner", "expr": "ring1_outer - ring_width" },
    { "name": "ring1_middle", "expr": "(ring1_outer + ring1_inner) / 2" },
    { "name": "arc_size", "expr": "220" }
  ],
  "transform": [
    { "as": "ratio", "calculate": "datum['$valueField'] / datum['$totalField']" },
    { "as": "_arc_start_degrees", "calculate": "360 - ( arc_size / 2 )" },
    { "as": "_arc_end_degrees", "calculate": "0 + ( arc_size / 2 )" },
    { "as": "_arc_start_radians", "calculate": "2 * 3.14 * ( datum['_arc_start_degrees'] - 360 ) / 360" },
    { "as": "_arc_end_radians", "calculate": "2 * 3.14 * datum['_arc_end_degrees'] / 360" },
    { "as": "_arc_total_radians", "calculate": "datum['_arc_end_radians'] - datum['_arc_start_radians']" },
    { "as": "_ring_start_radians", "calculate": "datum['_arc_start_radians']" },
    {
      "as": "_ring_end_radians",
      "calculate": "datum['_arc_start_radians'] + ( datum['_arc_total_radians'] * datum['ratio'] )"
    }
  ],
  "layer": [
    {
      "mark": {
        "type": "arc",
        "color": "lightgrey",
        "theta": { "expr": "datum['_arc_start_radians']" },
        "radius": { "expr": "ring1_outer" },
        "theta2": { "expr": "datum['_arc_end_radians']" },
        "radius2": { "expr": "ring1_inner" },
        "cornerRadius": 10
      }
    },
    {
      "name": "RING",
      "mark": {
        "type": "arc",
        "theta": { "expr": "datum['_ring_start_radians']" },
        "radius": { "expr": "ring1_outer" },
        "theta2": { "expr": "datum['_ring_end_radians']" },
        "radius2": { "expr": "ring1_inner" },
        "cornerRadius": 10
      },
      "encoding": {
        "color": {
          "value": "#307E31",
          "condition": [
            { "test": "datum['ratio'] < 0.33", "value": "#880808" },
            { "test": "datum['ratio'] < 0.66", "value": "#E49B0F" }
          ]
        }
      }
    },
    {
      "mark": { "type": "text", "fontSize": 40 },
      "encoding": {
        "text": { "field": "$valueField" },
        "color": {
          "value": "#307E31",
          "condition": [
            { "test": "datum['ratio'] < 0.33", "value": "#880808" },
            { "test": "datum['ratio'] < 0.66", "value": "#E49B0F" }
          ]
        }
      }
    }
  ]
}

Graphique radar

Exemple de graphique radar.

Définissez $key et $value dans la section Champs .

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "width": "container",
  "height": "container",
  "config": {
    "autosize": { "type": "fit", "contains": "padding" }
  },
  "data": { "name": "databricks_query" },
  "transform": [
    { "window": [{ "op": "row_number", "as": "category" }] },
    { "calculate": "datum.category - 1", "as": "category" },
    {
      "joinaggregate": [
        { "op": "count", "as": "numCategories" },
        { "op": "max", "field": "$value", "as": "maxValue" }
      ]
    },
    { "calculate": "2 * PI * datum.category / datum.numCategories", "as": "angle" },
    { "calculate": "100 * datum['$value'] / datum.maxValue", "as": "r" },
    { "calculate": "datum.r * cos(datum.angle)", "as": "x" },
    { "calculate": "datum.r * sin(datum.angle)", "as": "y" },
    { "calculate": "110 * cos(datum.angle)", "as": "label_x" },
    { "calculate": "110 * sin(datum.angle)", "as": "label_y" }
  ],
  "layer": [
    {
      "transform": [
        { "joinaggregate": [{ "op": "count", "as": "numCategories" }] },
        { "aggregate": [{ "op": "max", "field": "numCategories", "as": "numCategories" }] },
        { "calculate": "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]", "as": "cats" },
        { "flatten": ["cats"], "as": ["cat"] },
        { "filter": "datum.cat <= datum.numCategories" },
        { "calculate": "2 * PI * datum.cat / datum.numCategories", "as": "angle" },
        { "calculate": "100 * cos(datum.angle)", "as": "x" },
        { "calculate": "100 * sin(datum.angle)", "as": "y" }
      ],
      "mark": { "type": "line", "color": "#ddd", "strokeWidth": 1 },
      "encoding": {
        "x": { "field": "x", "type": "quantitative", "scale": { "domain": [-120, 120] }, "axis": null },
        "y": { "field": "y", "type": "quantitative", "scale": { "domain": [-120, 120] }, "axis": null },
        "order": { "field": "cat" }
      }
    },
    {
      "transform": [
        { "joinaggregate": [{ "op": "count", "as": "numCategories" }] },
        { "aggregate": [{ "op": "max", "field": "numCategories", "as": "numCategories" }] },
        { "calculate": "[20,40,60,80,100]", "as": "levels" },
        { "flatten": ["levels"], "as": ["level"] },
        { "calculate": "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]", "as": "cats" },
        { "flatten": ["cats"], "as": ["cat"] },
        { "filter": "datum.cat <= datum.numCategories" },
        { "calculate": "2 * PI * datum.cat / datum.numCategories", "as": "angle" },
        { "calculate": "datum.level", "as": "r" },
        { "calculate": "datum.r * cos(datum.angle)", "as": "x" },
        { "calculate": "datum.r * sin(datum.angle)", "as": "y" }
      ],
      "mark": { "type": "line", "color": "#ddd", "strokeWidth": 1 },
      "encoding": {
        "x": { "field": "x", "type": "quantitative" },
        "y": { "field": "y", "type": "quantitative" },
        "detail": { "field": "level" },
        "order": { "field": "cat" }
      }
    },
    {
      "mark": { "type": "line", "color": "#9467bd", "strokeWidth": 2, "interpolate": "linear-closed" },
      "encoding": {
        "x": { "field": "x", "type": "quantitative" },
        "y": { "field": "y", "type": "quantitative" },
        "order": { "field": "category" }
      }
    },
    {
      "mark": { "type": "point", "filled": true, "size": 50, "color": "#9467bd" },
      "encoding": {
        "x": { "field": "x", "type": "quantitative" },
        "y": { "field": "y", "type": "quantitative" }
      }
    },
    {
      "mark": { "type": "text", "fontSize": 14, "fontWeight": "bold" },
      "encoding": {
        "x": { "field": "label_x", "type": "quantitative" },
        "y": { "field": "label_y", "type": "quantitative" },
        "text": { "field": "$key", "type": "nominal" }
      }
    }
  ],
  "view": { "stroke": null }
}

Graphique radial

Exemple de graphique radial.

Définissez $valueField et $colorField dans la section Champs .

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
  "width": "container",
  "height": "container",
  "config": {
    "autosize": { "type": "fit", "contains": "padding" }
  },
  "data": { "name": "databricks_query" },
  "transform": [
    {
      "aggregate": [{ "op": "sum", "field": "$valueField", "as": "total" }],
      "groupby": ["$colorField"]
    },
    {
      "window": [{ "op": "rank", "as": "rank" }],
      "sort": [{ "field": "total", "order": "descending" }]
    }
  ],
  "layer": [
    {
      "mark": { "type": "arc", "innerRadius": 20, "stroke": "#fff" }
    }
  ],
  "encoding": {
    "theta": {
      "field": "total",
      "type": "quantitative",
      "scale": { "type": "sqrt" },
      "stack": true,
      "sort": "descending"
    },
    "radius": { "field": "total", "scale": { "type": "sqrt", "zero": true } },
    "color": {
      "field": "$colorField",
      "type": "nominal",
      "title": "Sub-Category",
      "sort": { "field": "total", "order": "descending" },
      "legend": { "orient": "right" }
    },
    "tooltip": [
      { "field": "$colorField", "type": "nominal", "title": "Sub-Category" },
      { "field": "total", "type": "quantitative", "title": "Sales" }
    ]
  },
  "view": { "stroke": null }
}

Graphique en rayons de soleil

Exemple de graphique en rayons de soleil.

Définissez outerGroupField, innerGroupFieldet sizeField dans la section Champs .

Spécification JSON
{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "width": "container",
  "height": "container",
  "data": { "name": "databricks_query" },
  "config": {
    "autosize": { "type": "fit", "contains": "padding" }
  },
  "transform": [
    { "calculate": "datum['outerGroupField']", "as": "OUTSIDE" },
    { "calculate": "datum['innerGroupField']", "as": "INSIDE" },
    { "calculate": "datum.OUTSIDE + '-' + datum.INSIDE", "as": "OUT_IN" },
    { "calculate": "toNumber(datum['sizeField'])", "as": "SIZE" }
  ],
  "resolve": {
    "scale": { "color": "independent" },
    "legend": { "color": "independent" }
  },
  "layer": [
    {
      "mark": {
        "type": "arc",
        "tooltip": true,
        "innerRadius": { "expr": "min(width, height)/9" },
        "outerRadius": { "expr": "min(width, height)/3" }
      },
      "encoding": {
        "theta": { "field": "SIZE", "type": "quantitative", "stack": true },
        "color": {
          "field": "OUT_IN",
          "type": "ordinal",
          "sort": "ascending",
          "title": "Inner Grouping",
          "scale": {
            "range": [
              "#1DF9B9",
              "#1DE5B9",
              "#1DD1B9",
              "#1DBDB9",
              "#1DA9B9",
              "#3DF23B",
              "#3DDA3B",
              "#3DC23B",
              "#3DAA3B",
              "#3D923B"
            ]
          }
        },
        "order": { "field": "OUT_IN", "sort": "ascending" },
        "tooltip": [
          { "field": "OUTSIDE", "type": "nominal", "title": "Outer Grouping" },
          { "field": "INSIDE", "type": "nominal", "title": "Inner Grouping" },
          { "field": "SIZE", "type": "quantitative", "title": "Count" }
        ]
      }
    },
    {
      "transform": [
        {
          "aggregate": [{ "op": "sum", "field": "SIZE", "as": "total_users" }],
          "groupby": ["OUTSIDE"]
        }
      ],
      "mark": {
        "type": "arc",
        "tooltip": true,
        "innerRadius": { "expr": "min(width, height)/3" }
      },
      "encoding": {
        "theta": {
          "field": "total_users",
          "type": "quantitative",
          "stack": true,
          "sort": "ascending",
          "title": "Users Count"
        },
        "color": {
          "field": "OUTSIDE",
          "type": "ordinal",
          "sort": "ascending",
          "title": "Outer Grouping",
          "scale": { "range": ["#1DD1B9", "#3DC23B"] }
        },
        "order": { "field": "OUTSIDE", "sort": "ascending" },
        "tooltip": [
          { "field": "OUTSIDE", "type": "nominal", "title": "Outer Grouping" },
          { "field": "total_users", "type": "quantitative", "title": "Count" }
        ]
      }
    }
  ]
}

Limitations

  • Les graphiques Treemap ne sont pas pris en charge. Vega-Lite ne prend pas en charge les treemaps.
  • Le filtre croisé ne prend en charge que les sélections de points. Les sélections d’intervalles (pinceau) ne se filtrent pas de façon croisée.
  • Le filtre croisé par défaut ne s’applique qu’aux spécifications à vue unique. Les spécifications en couches et multi-vues doivent déclarer le paramètre databricks_mark_selection pour effectuer un filtrage croisé.
  • Une visualisation personnalisée prend en charge un paramètre de sélection de filtre croisé. Si une spécification déclare databricks_mark_selection plus d’une fois, seule la première effectue le filtrage croisé.
  • Les marques d’image prennent uniquement en charge les URL d’image en base64 data: inline (par exemple data:image/png;base64,...) de 37 Ko ou moins, au format PNG, JPEG ou WebP. Les URL d’image distantes (https: ou http:), les URL relatives, les images SVG et les URL d’image pilotées par des champs ou des expressions ne sont pas prises en charge.