Interaction
In this tutorial we will be going over the basic interactions in Vega-Lite. We will be using faceting, multiple linked views, sorting, brushing, filtering, selections and tooltips.
Libraries and Data Imports
d3 = require("https://d3js.org/d3.v5.js")
VegaLite = require("@observablehq/vega-lite@0.1")
data = d3.csv("https://vega.github.io/vega-lite/data/seattle-weather.csv")
Multiple takes on Multiple Views
First we need to go over the various ways to combine views together
Concatenation
We can use "hconcat" and "vconcat" to combine different views together
VegaLite( { data: {values: data}, hconcat: [{ mark: { type: "point",filled: "true"}, encoding: { x: { field: "precipitation", type: "quantitative"}, y: {field: "wind", type: "quantitative"}, color: {field: "weather", type: "nominal"} }, }, { mark: {type: "point",filled: "true"}, encoding: { x: { field: "temp_max", type: "quantitative"}, y: {field: "wind", type: "quantitative"}, color: {field: "weather", type: "nominal"} }, }] })
HTML Table
Equivalently, and prehaps with more custamizeability we can create cells with names for each visualization and then combine them into an HTML table
PW = VegaLite( { data: {values: data}, mark: {type: "point",filled: "true"}, encoding: { x: { field: "precipitation", type: "quantitative"}, y: {field: "wind", type: "quantitative"}, color: {field: "weather", type: "nominal"} } })
TW = VegaLite( { data: {values: data}, mark: {type: "point",filled: "true"}, encoding: { x: { field: "temp_max", type: "quantitative"}, y: {field: "wind", type: "quantitative"}, color: {field: "weather", type: "nominal"} } })
html`<table style="width:100%"> <tr> <td>${TW}</td> <td>${PW}</td> </tr> </table>`
"Repeat" Operator for small multiples"
We can use the "repeat" operator for both columns and rows to make a matrix and encode values from these channels to axis or other encodings.
VegaLite({ data: {values: data}, repeat: { column: ["temp_max", "wind", "precipitation"], row: ["precipitation", "wind", "temp_max"] }, spec: { mark: "point", encoding:{ x: {field: {repeat: "column"}, type: "quantitative"}, y: {field: {repeat: "row"}, type: "quantitative"}, color: {field: "weather", type: "nominal"} } } })
Faceting
We can create multiple displays using various columns using the repeat operator, or we can also use faceting to drill down on values within a particular column
VegaLite({ data: {values: data}, facet: {column: {field: "weather", type: "nominal"}}, spec: { width: 120, height: 120, mark: "bar", encoding: { x: {bin: "true", field: "wind", type: "quantitative"}, y: {aggregate: "count", type: "quantitative"} } } })
Interactions
Tooltips
Tooltip based on underlying data with a bar chart
VegaLite({ data: {values: data}, mark: "bar", encoding: { x: {field: "weather", type: "nominal"}, y: {aggregate: "count", field: "*", type: "quantitative"}, tooltip: [ {field: "weather", type:"nominal"}, {aggregate: "mean", field: "precipitation", type: "quantitative"} ] } })
Overview and Detail
Here we can use a brush interaction to zoom in on a subset of the timeseries data to zoom in on details while maintaining the context
VegaLite({ data: {values: data}, vconcat: [{ mark: "area", width: 480, encoding: { x: { field: "date", type: "temporal", scale: {domain: {selection: "brush"}}, axis: {title: ""} }, y: {field: "temp_max", type: "quantitative"} } }, { height: 60, width: 480, mark: "area", selection: { brush: {type: "interval", encodings: ["x"]} }, encoding: { x: { field: "date", type: "temporal" }, y: { field: "temp_max", type: "quantitative", axis: {tickCount: 2, gride: false} } } }] })
Brushing and Highlighting
We can use highlighting with various forms of logic to explore data from multiple displays
VegaLite({ data: {values: data}, repeat: { column: ["temp_max", "wind", "precipitation"], row: ["precipitation", "wind", "temp_max"] }, spec: { mark: "point", selection:{ brush: {type: "interval", resolve: "intersect"} }, encoding: { x: {field: {repeat: "column"}, type: "quantitative"}, y: {field: {repeat: "row"}, type: "quantitative"}, color: {condition: {selection: "brush", field: "weather", type: "nominal"}, value: "grey"}, } } })
Brushing and Filtering
VegaLite( { data: {values: data}, hconcat: [{ selection: {brush: {type: "interval"}}, mark: { type: "point",filled: "true"}, encoding: { x: { field: "precipitation", type: "quantitative"}, y: {field: "temp_min", type: "quantitative"}, color: {field: "weather", type: "nominal"} }, }, { transform: [ {filter: {selection: "brush"}} ], mark: {type: "point",filled: "true"}, encoding: { x: { field: "temp_max", type: "quantitative", scale: {domain: [-5, 40]}}, y: {field: "wind", type: "quantitative", scale: {domain: [0, 10]}}, color: {field: "weather", type: "nominal"} }, }] })
'Cross-filtering' using 'layers'
VegaLite({ data: {values: data}, repeat: {column: ["wind", "precipitation", "temp_max"]}, spec: { width: 120, height: 120, layer: [{ selection: {brush: {type: "interval", encodings: ["x"]}}, mark: "bar", encoding: { y: {aggregate: "count", type: "quantitative"}, x: {field: {repeat: "column"}, bin: "true", type: "quantitative"} } }, { transform: [{filter: {selection: "brush"}}], mark: "bar", encoding: { y: {aggregate: "count", type: "quantitative"}, x: { field: {repeat: "column"}, bin: "true", type: "quantitative"}, color: {value: "goldenrod"} } }] } })
Linked Dashboard with various selection (single and interval) and interaction (highlight and filter) types
VegaLite({ data: {values: data}, vconcat: [ { mark: "point", encoding: { x: {timeUnit: "monthdate", field: "date", type: "temporal"}, y: {field: "temp_max", type: "quantitative"}, color: { condition: { field: "weather", selection: "click", type: "nominal" }, value: "lightgray" }, size: {field: "precipitation", type: "quantitative", scale: {domain: [1, 50]}}, }, width: 800, height: 400, selection: {brush: {encodings: ["x"], type: "interval"}} }, { encoding: { color: { condition: { field: "weather", title: "weather", selection: "click", type: "nominal" }, value: "lightgray" }, x: {aggregate: "count", type: "quantitative"}, y: {field: "weather", type: "nominal"} }, width: 800, mark: "bar", selection: {click: {encodings: ["color"], type: "multi"}}, transform: [{filter: {selection: "brush"}}] } ] })
Challenge
Create an interactive visualization using one view composition method and two interaction methods.
VegaLite({ data: {values: data}, vconcat: [ { mark: "area", encoding: { x: {timeUnit: "monthdate", field: "date", type: "temporal"}, y: {field: "temp_max", type: "quantitative"}, color: { condition: { field: "weather", selection: "click", type: "nominal" }, value: "lightgray" }, size: {field: "precipitation", type: "quantitative", scale: {domain: [1, 50]}}, }, width: 800, height: 400, selection: {brush: {encodings: ["x"], type: "interval"}} }, { encoding: { color: { condition: { field: "weather", title: "weather", selection: "click", type: "nominal" }, value: "lightgray" }, x: {aggregate: "count", type: "quantitative"}, y: {field: "precipitation", type: "quantitative"} }, width: 800, mark: "bar", selection: {click: {encodings: ["color"], type: "multi"}}, transform: [{filter: {selection: "brush"}}] } ] })