Density Heatmaps Example

A trellis plot of density estimates for automobile statistics, partitioned by region of origin. The density grids produced by the kde2d transform are rendered as images by the heatmap transform. By default each heatmap is normalized independently. If resolve equals “shared”, the heatmaps instead show probability or count densities normalized by the global maximum across plots. This example generates heatmaps as rendered image marks. For an example that instead uses a grid of rect marks, see the Heatmap example.

Vega JSON Specification <>

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A small multiples view of 2D density heatmaps of automobile statistics.",
  "width": 250,
  "height": 250,
  "padding": 5,
  "autosize": "pad",

  "signals": [
    {
      "name": "fieldX", "value": "Acceleration",
      "bind": {"input": "select", "options": ["Acceleration", "Displacement", "Horsepower"]}
    },
    {
      "name": "bandwidthX", "value": -1,
      "bind": {"input": "range", "min": -1, "max": 100, "step": 1}
    },
    {
      "name": "bandwidthY", "value": -1,
      "bind": {"input": "range", "min": -1, "max": 100, "step": 1}
    },
    {
      "name": "resolve", "value": "independent",
      "bind": {"input": "select", "options": ["independent", "shared"]}
    },
    {
      "name": "counts", "value": false,
      "bind": {"input": "checkbox"}
    },
    {
      "name": "smooth", "value": true,
      "bind": {"input": "checkbox"}
    },
    {
      "name": "cellSize", "value": 4,
      "bind": {"input": "select", "options": [1, 2, 4, 8, 16]}
    },
    {
      "name": "title", "value": "Density",
      "update": "[if(resolve == 'shared', 'Global' + if(counts, ' Count', ' Prob.'), 'Local Density'), '(Normalized)']"
    }
  ],

  "data": [
    {
      "name": "source",
      "url": "data/cars.json",
      "transform": [
        {
          "type": "filter",
          "expr": "datum[fieldX] != 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[fieldX])"},
          "y": {"expr": "scale('y', datum.Miles_per_Gallon)"},
          "bandwidth": {"signal": "[bandwidthX, bandwidthY]"},
          "cellSize": {"signal": "cellSize"},
          "counts": {"signal": "counts"}
        },
        {
          "type": "heatmap",
          "field": "grid",
          "resolve": {"signal": "resolve"},
          "color": {"expr": "scale('density', datum.$value / datum.$max)"},
          "opacity": 1
        }
      ]
    }
  ],

  "scales": [
    {
      "name": "x",
      "type": "linear",
      "round": true,
      "nice": true,
      "zero": true,
      "domain": {"data": "source", "field": {"signal": "fieldX"}},
      "range": "width"
    },
    {
      "name": "y",
      "type": "linear",
      "round": true,
      "nice": true,
      "zero": true,
      "domain": {"data": "source", "field": "Miles_per_Gallon"},
      "range": "height"
    },
    {
      "name": "density",
      "type": "linear",
      "zero": true,
      "domain": [0, 1],
      "range": {"scheme": "viridis"}
    }
  ],

  "axes": [
    {
      "scale": "y",
      "domain": false,
      "orient": "left",
      "titlePadding": 5,
      "title": "Miles per Gallon",
      "offset": 2
    }
  ],

  "legends": [
    {
      "fill": "density",
      "title": {"signal": "title"},
      "gradientLength": {"signal": "height - 28"}
    }
  ],

  "layout": {
    "bounds": "flush",
    "columns": 3,
    "padding": 10
  },

  "marks": [
    {
      "type": "group",
      "from": {
        "facet": {
          "name": "facet",
          "data": "density",
          "groupby": "Origin"
        }
      },

      "sort": {"field": "datum.Origin", "order": "ascending"},

      "title": {
        "text": {"signal": "parent.Origin"},
        "frame": "group"
      },

      "encode": {
        "update": {
          "width": {"signal": "width"},
          "height": {"signal": "height"}
        }
      },

      "axes": [
        {
          "scale": "x",
          "domain": false,
          "orient": "bottom",
          "tickCount": 5,
          "labelFlush": true,
          "title": {"signal": "fieldX"}
        }
      ],

      "marks": [
        {
          "type": "image",
          "from": {"data": "facet"},
          "encode": {
            "update": {
              "x": {"value": 0},
              "y": {"value": 0},
              "image": {"field": "image"},
              "width": {"signal": "width"},
              "height": {"signal": "height"},
              "aspect": {"value": false},
              "smooth": {"signal": "smooth"}
            }
          }
        }
      ]
    }
  ]
}