Contour Plot Example

A contour plot depicts the density of data points as a set of discrete levels. Akin to contour lines on topographic maps, each contour boundary is an isoline of constant density. Kernel density estimation is performed with the kde2d transform to generate a continuous approximation of the sample density for each group. The heatmap transform generates heatmap images to convey these density estimates directly. The isocontour transform analyzes the density estimates to generate level set contours in the form of GeoJSON polygons.

Vega JSON Specification <>

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A contour plot example, overlaying a density estimate on scatter plot points.",
  "width": 500,
  "height": 400,
  "padding": 5,
  "autosize": "pad",

  "signals": [
    {
      "name": "bandwidth", "value": -1,
      "bind": {"input": "range", "min": -1, "max": 100, "step": 1}
    },
    {
      "name": "resolve", "value": "shared",
      "bind": {"input": "select", "options": ["independent", "shared"]}
    },
    {
      "name": "counts", "value": true,
      "bind": {"input": "checkbox"}
    }
  ],

  "data": [
    {
      "name": "source",
      "url": "data/cars.json",
      "transform": [
        {
          "type": "filter",
          "expr": "datum.Horsepower != null && datum.Miles_per_Gallon != null"
        }
      ]
    },
    {
      "name": "density",
      "source": "source",
      "transform": [
        {
          "type": "kde2d",
          "groupby": ["Origin"],
          "size": [{"signal": "width"}, {"signal": "height"}],
          "x": {"expr": "scale('x', datum.Horsepower)"},
          "y": {"expr": "scale('y', datum.Miles_per_Gallon)"},
          "bandwidth": {"signal": "[bandwidth, bandwidth]"},
          "counts": {"signal": "counts"}
        }
      ]
    },
    {
      "name": "contours",
      "source": "density",
      "transform": [
        {
          "type": "isocontour",
          "field": "grid",
          "resolve": {"signal": "resolve"},
          "levels": 3
        }
      ]
    }
  ],

  "scales": [
    {
      "name": "x",
      "type": "linear",
      "round": true,
      "nice": true,
      "zero": true,
      "domain": {"data": "source", "field": "Horsepower"},
      "range": "width"
    },
    {
      "name": "y",
      "type": "linear",
      "round": true,
      "nice": true,
      "zero": true,
      "domain": {"data": "source", "field": "Miles_per_Gallon"},
      "range": "height"
    },
    {
      "name": "color",
      "type": "ordinal",
      "domain": {
        "data": "source", "field": "Origin",
        "sort": {"order": "descending"}
      },
      "range": "category"
    }
  ],

  "axes": [
    {
      "scale": "x",
      "grid": true,
      "domain": false,
      "orient": "bottom",
      "tickCount": 5,
      "title": "Horsepower"
    },
    {
      "scale": "y",
      "grid": true,
      "domain": false,
      "orient": "left",
      "titlePadding": 5,
      "title": "Miles_per_Gallon"
    }
  ],

  "legends": [
    {"stroke": "color", "symbolType": "stroke"}
  ],

  "marks": [
    {
      "name": "marks",
      "type": "symbol",
      "from": {"data": "source"},
      "encode": {
        "update": {
          "x": {"scale": "x", "field": "Horsepower"},
          "y": {"scale": "y", "field": "Miles_per_Gallon"},
          "size": {"value": 4},
          "fill": {"value": "#ccc"}
        }
      }
    },
    {
      "type": "image",
      "from": {"data": "density"},
      "encode": {
        "update": {
          "x": {"value": 0},
          "y": {"value": 0},
          "width": {"signal": "width"},
          "height": {"signal": "height"},
          "aspect": {"value": false}
        }
      },
      "transform": [
        {
          "type": "heatmap",
          "field": "datum.grid",
          "resolve": {"signal": "resolve"},
          "color": {"expr": "scale('color', datum.datum.Origin)"}
        }
      ]
    },
    {
      "type": "path",
      "clip": true,
      "from": {"data": "contours"},
      "encode": {
        "enter": {
          "strokeWidth": {"value": 1},
          "strokeOpacity": {"value": 1},
          "stroke": {"scale": "color", "field": "Origin"}
        }
      },
      "transform": [
        { "type": "geopath", "field": "datum.contour" }
      ]
    }
  ]
}