Deneb Example - Lasagna Plot

Deneb/Vega-Lite can be used to create a Lasagna Plot, an alternative to a spaghetti plot, and can enhance the visualization and interpretation of insights from large datasets. (Large datasets visualized with spaghetti plots can be cluttered and obscure data trends.) The example presented herein uses an area chart of the NASDAQ composite index to refine the selection of the date range of interest and a lasagna plot of the normalized % difference of close price from the overall period mean for several stocks (the lasagna plot is coloured using a red-yellow-green gradient colour scale with offset mid-point [-100% red; 0% yellow; +500% green] and a full-width horizontal legend).

(The video shows the short, real-time rendering pauses that can occur when using large datasets with Deneb.)

This example illustrates a number of Deneb/Vega-Lite features, including:
0 - General:

  • use of a “title” block with title and subtitle
  • use of a “transform” block to extend the dataset with in-visual calculations of the symbol mean, variance and % variance
  • use of a “vconcat” block with an area chart for the NASDAQ composite index above a lasagna plot of the stock close price % variance

1 - Area Chart:

  • use of an “area” mark with index close price (Y) vs. date (X) and 50% colour opacity
  • use of a standalone “title” block
  • use of a “transform” block to filter the dataset to contain only NASDAQ Composite Index records
  • use of a “params” block with a mouse-driven selection brush

2 - Lasagna Plot:

  • use of a “rect” mark of stock symbol (Y) vs. date (X) (date range is filtered by the selection brush in the area chart), with 50% colour opacity
  • use of a standalone “title” block
  • use of a “transform” block to filter the dataset to contain only stock records
  • use of a “color” block of % variance with a horizontal full-width gradient legend
    • (legend has range -100% to +500% with mid-point offset to 0%)
  • use of the available no-code Vega-Lite “redyellowgreen” diverging gradient colour scale (same as Vega)
  • use of a custom tooltip using Deneb syntax (symbol, date, close price, symbol mean price, % variance)
Deneb/Vega-Lite JSON Code
{
  "title": {
    "text": "Power BI Lasagna Plot using Deneb",
    "anchor": "start",
    "align": "left",
    "fontSize": 32,
    "fontWeight": "bold",
    "subtitle": "Stock Performance by Company",
    "subtitleFontSize": 12,
    "subtitleFontStyle": "italic",
    "offset": 10
  },
  "data": {"name": "dataset"},
  "spacing": 40,
  "transform": [
    {
      "joinaggregate": [
        {
          "op": "mean",
          "field": "Close",
          "as": "_symbol_mean"
        }
      ],
      "groupby": ["Symbol"]
    },
    {
      "calculate": "datum['Close'] - datum['_symbol_mean']",
      "as": "_variance"
    },
    {
      "calculate": "datum['_variance'] / datum['_symbol_mean']",
      "as": "_variance_percent"
    }
  ],
  "vconcat": [
    {
      "name": "NASDAQ_DATE_SELECTOR",
      "width": 1200,
      "height": 100,
      "title": {
        "text": "NASDAQ Composite Index",
        "anchor": "middle",
        "fontSize": 18,
        "fontWeight": "bold",
        "fontStyle": "italic"
      },
      "transform": [
        {
          "filter": "datum['Symbol'] == 'NASDAQ'"
        }
      ],
      "mark": {
        "type": "area",
        "color": "#0F4C81",
        "opacity": 0.5
      },
      "params": [
        {
          "name": "brush",
          "select": {
            "type": "interval",
            "encodings": ["x"]
          }
        }
      ],
      "encoding": {
        "y": {
          "field": "Close",
          "type": "quantitative",
          "title": null
        },
        "x": {
          "field": "Date",
          "type": "temporal",
          "timeUnit": "yearmonthdate",
          "title": null,
          "axis": {"format": "%b %Y"}
        }
      }
    },
    {
      "name": "LASAGNA_PLOT",
      "width": 1200,
      "height": 400,
      "title": {
        "text": "Stock Performance",
        "anchor": "middle",
        "fontSize": 18,
        "fontWeight": "bold",
        "fontStyle": "italic",
        "offset": 60
      },
      "transform": [
        {
          "filter": "datum['Symbol'] != 'NASDAQ'"
        }
      ],
      "mark": {
        "type": "rect",
        "tooltip": true,
        "opacity": 0.5
      },
      "encoding": {
        "y": {
          "field": "Symbol",
          "type": "nominal",
          "title": null,
          "axis": {
            "labelExpr": "datum.value == 'AAPL' ? 'Apple' : datum.value == 'AMZN' ? 'Amazon' : datum.value == 'GOOG' ? 'Google' : datum.value == 'IBM' ? 'IBM' : datum.value == 'INTC' ? 'Intel' : datum.value == 'LOGI' ? 'Logitech' : datum.value == 'MSFT' ? 'Microsoft' : datum.value == 'NVDA' ? 'NVIDIA' : null"
          }
        },
        "x": {
          "field": "Date",
          "type": "temporal",
          "timeUnit": "yearmonthdate",
          "scale": {
            "domain": {"param": "brush"}
          },
          "title": null,
          "axis": {"format": "%d-%b-%y"}
        },
        "color": {
          "field": "_variance_percent",
          "type": "quantitative",
          "scale": {
            "scheme": "redyellowgreen",
            "domainMid": 0,
            "domain": [-1, 5]
          },
          "legend": {
            "orient": "top",
            "direction": "horizontal",
            "offset": -260,
            "format": ".0%",
            "titleLimit": 400,
            "title": "Variance from Stock Overall Period Mean",
            "gradientLength": 1200,
            "values": [
              -1,
              0,
              1,
              2,
              3,
              4,
              5
            ]
          }
        },
        "tooltip": [
          {
            "field": "Symbol",
            "type": "nominal"
          },
          {
            "field": "Date",
            "type": "temporal"
          },
          {
            "field": "Close",
            "type": "quantitative",
            "format": "$,.2f",
            "title": "Symbol Close"
          },
          {
            "field": "_symbol_mean",
            "type": "quantitative",
            "format": "$,.2f",
            "title": "Symbol Mean"
          },
          {
            "field": "_variance_percent",
            "type": "quantitative",
            "format": ".2%",
            "title": "Variance"
          }
        ]
      }
    }
  ]
}

The intent of this example is not to provide a finished visual, but rather to serve as a starting point for further custom visual development.

Also included is the development sample PBIX using public data from Yahoo Finance for the NASDAQ composite index and 8 sample tech stocks for the period 2000-01-01 to 2023-11-30, comprising a total of over 50,000 records. (With the most restrictive filtering [date range = 2011 to 2000; symbols = AAPL, IBM, INTC, LOGI, MSFT, NASDAQ, NVDA], the dataset still comprised over 19,000 records.)

This example is provided as-is for information purposes only, and its use is solely at the discretion of the end user; no responsibility is assumed by the author.

Greg
Deneb Examples - Lasagna Plot - V3.pbix (4.2 MB)

4 Likes

marking as solved

Fantastic as always @Greg :tada: :tada:

Greg, thank you very much
but I can’t see any tooltips

Deneb 1.6.1 issue … will be fixed in 1.6.2 … see this thread for more details: